Abstract.php 12 KB

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