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