Abstract.php 12 KB

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