TeamSpeak 3 PHP Framework  1.1.23
Copyright © Planet TeamSpeak. All rights reserved.
 All Classes Namespaces Files Functions Variables Pages
Abstract.php
Go to the documentation of this file.
1 <?php
2 
3 /**
4  * @file
5  * TeamSpeak 3 PHP Framework
6  *
7  * $Id: Abstract.php 10/11/2013 11:35:21 scp@orilla $
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  *
22  * @package TeamSpeak3
23  * @version 1.1.23
24  * @author Sven 'ScP' Paulsen
25  * @copyright Copyright (c) 2010 by Planet TeamSpeak. All rights reserved.
26  */
27 
28 /**
29  * @class TeamSpeak3_Node_Abstract
30  * @brief Abstract class describing a TeamSpeak 3 node and all it's parameters.
31  */
32 abstract class TeamSpeak3_Node_Abstract implements RecursiveIterator, ArrayAccess, Countable
33 {
34  /**
35  * @ignore
36  */
37  protected $parent = null;
38 
39  /**
40  * @ignore
41  */
42  protected $server = null;
43 
44  /**
45  * @ignore
46  */
47  protected $nodeId = 0x00;
48 
49  /**
50  * @ignore
51  */
52  protected $nodeList = null;
53 
54  /**
55  * @ignore
56  */
57  protected $nodeInfo = array();
58 
59  /**
60  * @ignore
61  */
62  protected $storage = array();
63 
64  /**
65  * Sends a prepared command to the server and returns the result.
66  *
67  * @param string $cmd
68  * @param boolean $throw
69  * @return TeamSpeak3_Adapter_ServerQuery_Reply
70  */
71  public function request($cmd, $throw = TRUE)
72  {
73  return $this->getParent()->request($cmd, $throw);
74  }
75 
76  /**
77  * Uses given parameters and returns a prepared ServerQuery command.
78  *
79  * @param string $cmd
80  * @param array $params
81  * @return TeamSpeak3_Helper_String
82  */
83  public function prepare($cmd, array $params = array())
84  {
85  return $this->getParent()->prepare($cmd, $params);
86  }
87 
88  /**
89  * Prepares and executes a ServerQuery command and returns the result.
90  *
91  * @param string $cmd
92  * @param array $params
93  * @return TeamSpeak3_Adapter_ServerQuery_Reply
94  */
95  public function execute($cmd, array $params = array())
96  {
97  return $this->request($this->prepare($cmd, $params));
98  }
99 
100  /**
101  * Returns the parent object of the current node.
102  *
103  * @return TeamSpeak3_Adapter_ServerQuery
104  * @return TeamSpeak3_Node_Abstract
105  */
106  public function getParent()
107  {
108  return $this->parent;
109  }
110 
111  /**
112  * Returns the primary ID of the current node.
113  *
114  * @return integer
115  */
116  public function getId()
117  {
118  return $this->nodeId;
119  }
120 
121  /**
122  * Returns TRUE if the node icon has a local source.
123  *
124  * @param string $key
125  * @return boolean
126  */
127  public function iconIsLocal($key)
128  {
129  return ($this[$key] > 0 && $this[$key] < 1000) ? TRUE : FALSE;
130  }
131 
132  /**
133  * Returns the internal path of the node icon.
134  *
135  * @param string $key
136  * @return TeamSpeak3_Helper_String
137  */
138  public function iconGetName($key)
139  {
140  $iconid = ($this[$key] < 0) ? (pow(2, 32))-($this[$key]*-1) : $this[$key];
141 
142  return new TeamSpeak3_Helper_String("/icon_" . $iconid);
143  }
144 
145  /**
146  * Returns a possible classname for the node which can be used as a HTML property.
147  *
148  * @param string $prefix
149  * @return string
150  */
151  public function getClass($prefix = "ts3_")
152  {
153  if($this instanceof TeamSpeak3_Node_Channel && $this->isSpacer())
154  {
155  return $prefix . "spacer";
156  }
157  elseif($this instanceof TeamSpeak3_Node_Client && $this["client_type"])
158  {
159  return $prefix . "query";
160  }
161 
162  return $prefix . TeamSpeak3_Helper_String::factory(get_class($this))->section("_", 2)->toLower();
163  }
164 
165  /**
166  * Returns a unique identifier for the node which can be used as a HTML property.
167  *
168  * @return string
169  */
170  abstract public function getUniqueId();
171 
172  /**
173  * Returns the name of a possible icon to display the node object.
174  *
175  * @return string
176  */
177  abstract public function getIcon();
178 
179  /**
180  * Returns a symbol representing the node.
181  *
182  * @return string
183  */
184  abstract public function getSymbol();
185 
186  /**
187  * Returns the HTML code to display a TeamSpeak 3 viewer.
188  *
189  * @param TeamSpeak3_Viewer_Interface $viewer
190  * @return string
191  */
192  public function getViewer(TeamSpeak3_Viewer_Interface $viewer)
193  {
194  $html = $viewer->fetchObject($this);
195 
196  $iterator = new RecursiveIteratorIterator($this, RecursiveIteratorIterator::SELF_FIRST);
197 
198  foreach($iterator as $node)
199  {
200  $siblings = array();
201 
202  for($level = 0; $level < $iterator->getDepth(); $level++)
203  {
204  $siblings[] = ($iterator->getSubIterator($level)->hasNext()) ? 1 : 0;
205  }
206 
207  $siblings[] = (!$iterator->getSubIterator($level)->hasNext()) ? 1 : 0;
208 
209  $html .= $viewer->fetchObject($node, $siblings);
210  }
211 
212  return $html;
213  }
214 
215  /**
216  * Filters given node list array using specified filter rules.
217  *
218  * @param array $nodes
219  * @param array $rules
220  * @return array
221  */
222  protected function filterList(array $nodes = array(), array $rules = array())
223  {
224  if(!empty($rules))
225  {
226  foreach($nodes as $node)
227  {
228  if(!$node instanceof TeamSpeak3_Node_Abstract) continue;
229 
230  $props = $node->getInfo(FALSE);
231  $props = array_intersect_key($props, $rules);
232  $match = TRUE;
233 
234  foreach($props as $key => $val)
235  {
236  if($val instanceof TeamSpeak3_Helper_String)
237  {
238  $match = $val->contains($rules[$key], TRUE);
239  }
240  else
241  {
242  $match = $val == $rules[$key];
243  }
244 
245  if($match === FALSE)
246  {
247  unset($nodes[$node->getId()]);
248  }
249  }
250  }
251  }
252 
253  return $nodes;
254  }
255 
256  /**
257  * Returns all information available on this node. If $convert is enabled, some property
258  * values will be converted to human-readable values.
259  *
260  * @param boolean $extend
261  * @param boolean $convert
262  * @return array
263  */
264  public function getInfo($extend = TRUE, $convert = FALSE)
265  {
266  if($extend)
267  {
268  $this->fetchNodeInfo();
269  }
270 
271  if($convert)
272  {
273  $info = $this->nodeInfo;
274 
275  foreach($info as $key => $val)
276  {
278 
279  if($key->contains("_bytes_"))
280  {
281  $info[$key->toString()] = TeamSpeak3_Helper_Convert::bytes($val);
282  }
283  elseif($key->contains("_bandwidth_"))
284  {
285  $info[$key->toString()] = TeamSpeak3_Helper_Convert::bytes($val) . "/s";
286  }
287  elseif($key->contains("_packets_"))
288  {
289  $info[$key->toString()] = number_format($val, null, null, ".");
290  }
291  elseif($key->contains("_packetloss_"))
292  {
293  $info[$key->toString()] = sprintf("%01.2f", floatval($val->toString())*100) . "%";
294  }
295  elseif($key->endsWith("_uptime"))
296  {
297  $info[$key->toString()] = TeamSpeak3_Helper_Convert::seconds($val);
298  }
299  elseif($key->endsWith("_version"))
300  {
301  $info[$key->toString()] = TeamSpeak3_Helper_Convert::version($val);
302  }
303  elseif($key->endsWith("_icon_id"))
304  {
305  $info[$key->toString()] = $this->iconGetName($key)->filterDigits();
306  }
307  }
308 
309  return $info;
310  }
311 
312  return $this->nodeInfo;
313  }
314 
315  /**
316  * Returns the specified property or a pre-defined default value from the node info array.
317  *
318  * @param string $property
319  * @param mixed $default
320  * @return mixed
321  */
322  public function getProperty($property, $default = null)
323  {
324  if(!$this->offsetExists($property))
325  {
326  $this->fetchNodeInfo();
327  }
328 
329  if(!$this->offsetExists($property))
330  {
331  return $default;
332  }
333 
334  return $this->nodeInfo[(string) $property];
335  }
336 
337  /**
338  * Returns a string representation of this node.
339  *
340  * @return string
341  */
342  public function __toString()
343  {
344  return get_class($this);
345  }
346 
347  /**
348  * Returns a string representation of this node.
349  *
350  * @return string
351  */
352  public function toString()
353  {
354  return $this->__toString();
355  }
356 
357  /**
358  * Returns an assoc array filled with current node info properties.
359  *
360  * @return array
361  */
362  public function toArray()
363  {
364  return $this->nodeList;
365  }
366 
367  /**
368  * Called whenever we're using an unknown method.
369  *
370  * @param string $name
371  * @param array $args
372  * @throws TeamSpeak3_Node_Exception
373  * @return mixed
374  */
375  public function __call($name, array $args)
376  {
377  if($this->getParent() instanceof TeamSpeak3_Node_Abstract)
378  {
379  return call_user_func_array(array($this->getParent(), $name), $args);
380  }
381 
382  throw new TeamSpeak3_Node_Exception("node method '" . $name . "()' does not exist");
383  }
384 
385  /**
386  * Writes data to the internal storage array.
387  *
388  * @param string $key
389  * @param mixed $val
390  * @return void
391  */
392  protected function setStorage($key, $val)
393  {
394  $this->storage[$key] = $val;
395  }
396 
397  /**
398  * Returns data from the internal storage array.
399  *
400  * @param string $key
401  * @param mixed $default
402  * @return mixed
403  */
404  protected function getStorage($key, $default = null)
405  {
406  return (array_key_exists($key, $this->storage) && !empty($this->storage[$key])) ? $this->storage[$key] : $default;
407  }
408 
409  /**
410  * Deletes data from the internal storage array.
411  *
412  * @param string $key
413  * @return void
414  */
415  protected function delStorage($key)
416  {
417  unset($this->storage[$key]);
418  }
419 
420  /**
421  * Commit pending data.
422  *
423  * @return array
424  */
425  public function __sleep()
426  {
427  return array("parent", "storage", "nodeId");
428  }
429 
430  /**
431  * @ignore
432  */
433  protected function fetchNodeList()
434  {
435  $this->nodeList = array();
436  }
437 
438  /**
439  * @ignore
440  */
441  protected function fetchNodeInfo()
442  {
443  return;
444  }
445 
446  /**
447  * @ignore
448  */
449  protected function resetNodeInfo()
450  {
451  $this->nodeInfo = array();
452  }
453 
454  /**
455  * @ignore
456  */
457  protected function verifyNodeList()
458  {
459  if($this->nodeList === null)
460  {
461  $this->fetchNodeList();
462  }
463  }
464 
465  /**
466  * @ignore
467  */
468  protected function resetNodeList()
469  {
470  $this->nodeList = null;
471  }
472 
473  /**
474  * @ignore
475  */
476  public function count()
477  {
478  $this->verifyNodeList();
479 
480  return count($this->nodeList);
481  }
482 
483  /**
484  * @ignore
485  */
486  public function current()
487  {
488  $this->verifyNodeList();
489 
490  return current($this->nodeList);
491  }
492 
493  /**
494  * @ignore
495  */
496  public function getChildren()
497  {
498  $this->verifyNodeList();
499 
500  return $this->current();
501  }
502 
503  /**
504  * @ignore
505  */
506  public function hasChildren()
507  {
508  $this->verifyNodeList();
509 
510  return $this->current()->count() > 0;
511  }
512 
513  /**
514  * @ignore
515  */
516  public function hasNext()
517  {
518  $this->verifyNodeList();
519 
520  return $this->key()+1 < $this->count();
521  }
522 
523  /**
524  * @ignore
525  */
526  public function key()
527  {
528  $this->verifyNodeList();
529 
530  return key($this->nodeList);
531  }
532 
533  /**
534  * @ignore
535  */
536  public function valid()
537  {
538  $this->verifyNodeList();
539 
540  return $this->key() !== null;
541  }
542 
543  /**
544  * @ignore
545  */
546  public function next()
547  {
548  $this->verifyNodeList();
549 
550  return next($this->nodeList);
551  }
552 
553  /**
554  * @ignore
555  */
556  public function rewind()
557  {
558  $this->verifyNodeList();
559 
560  return reset($this->nodeList);
561  }
562 
563  /**
564  * @ignore
565  */
566  public function offsetExists($offset)
567  {
568  return array_key_exists((string) $offset, $this->nodeInfo) ? TRUE : FALSE;
569  }
570 
571  /**
572  * @ignore
573  */
574  public function offsetGet($offset)
575  {
576  if(!$this->offsetExists($offset))
577  {
578  $this->fetchNodeInfo();
579  }
580 
581  if(!$this->offsetExists($offset))
582  {
583  throw new TeamSpeak3_Adapter_ServerQuery_Exception("invalid parameter", 0x602);
584  }
585 
586  return $this->nodeInfo[(string) $offset];
587  }
588 
589  /**
590  * @ignore
591  */
592  public function offsetSet($offset, $value)
593  {
594  if(method_exists($this, "modify"))
595  {
596  return $this->modify(array((string) $offset => $value));
597  }
598 
599  throw new TeamSpeak3_Node_Exception("node '" . get_class($this) . "' is read only");
600  }
601 
602  /**
603  * @ignore
604  */
605  public function offsetUnset($offset)
606  {
607  unset($this->nodeInfo[(string) $offset]);
608  }
609 
610  /**
611  * @ignore
612  */
613  public function __get($offset)
614  {
615  return $this->offsetGet($offset);
616  }
617 
618  /**
619  * @ignore
620  */
621  public function __set($offset, $value)
622  {
623  $this->offsetSet($offset, $value);
624  }
625 }