/administrator/components/com_zoo/classes/tree.php

https://gitlab.com/vnsoftdev/amms · PHP · 341 lines · 97 code · 48 blank · 196 comment · 8 complexity · 9d8805cbc0481f51c0f52c531412ff57 MD5 · raw file

  1. <?php
  2. /**
  3. * @package com_zoo
  4. * @author YOOtheme http://www.yootheme.com
  5. * @copyright Copyright (C) YOOtheme GmbH
  6. * @license http://www.gnu.org/licenses/gpl.html GNU/GPL
  7. */
  8. /**
  9. * Base class to deal with tree structures
  10. *
  11. * @package Component.Classes
  12. */
  13. class AppTree {
  14. /**
  15. * A reference to the global App object
  16. *
  17. * @var App
  18. * @since 2.0
  19. */
  20. public $app;
  21. /**
  22. * The root node for the tree
  23. *
  24. * @var object
  25. * @since 2.0
  26. */
  27. protected $_root;
  28. /**
  29. * The class name
  30. *
  31. * @var string
  32. * @since 2.0
  33. */
  34. protected $_itemclass;
  35. /**
  36. * A list of filter methods to filter the tree
  37. *
  38. * @var array
  39. * @since 2.0
  40. */
  41. protected $_filters = array();
  42. /**
  43. * Class Constructor
  44. *
  45. * @param string $itemclass The name of the class we're dealing with
  46. * @since 2.0
  47. */
  48. public function __construct($itemclass = null) {
  49. $this->app = App::getInstance('zoo');
  50. if ($itemclass == null) {
  51. $itemclass = get_class($this).'Item';
  52. }
  53. $this->_root = $this->app->object->create($itemclass);
  54. $this->_itemclass = $itemclass;
  55. }
  56. /**
  57. * Add a tree filter
  58. *
  59. * @param string $filter Method name
  60. * @param array $args The list of arguments for the method
  61. *
  62. * @return AppTree $this for chaining support
  63. *
  64. * @since 2.0
  65. */
  66. public function addFilter($filter, $args = array()) {
  67. $this->_filters[] = compact('filter', 'args');
  68. return $this;
  69. }
  70. /**
  71. * Execute the filters on all the tree
  72. *
  73. * @return AppTree $this for chaining support
  74. *
  75. * @since 2.0
  76. */
  77. public function applyFilter() {
  78. foreach ($this->_filters as $filter) {
  79. $this->_root->filter($filter['filter'], $filter['args']);
  80. }
  81. return $this;
  82. }
  83. /**
  84. * Delegate the method calls to the AppTreeItem class
  85. *
  86. * @param string $method Method name
  87. * @param array $args List of arguments
  88. *
  89. * @return mixed Result of the method
  90. *
  91. * @since 2.0
  92. */
  93. public function __call($method, $args) {
  94. return call_user_func_array(array($this->_root, $method), $args);
  95. }
  96. }
  97. /**
  98. * Class that represents an item in the tree
  99. *
  100. * @package Component.Classes
  101. */
  102. class AppTreeItem {
  103. /**
  104. * Reference to the global app object
  105. *
  106. * @var App
  107. * @since 2.0
  108. */
  109. public $app;
  110. /**
  111. * THe parent item
  112. *
  113. * @var AppTreeItem
  114. * @since 2.0
  115. */
  116. protected $_parent;
  117. /**
  118. * List of children
  119. *
  120. * @var array
  121. * @since 2.0
  122. */
  123. protected $_children = array();
  124. /**
  125. * Get the item unique id (object hash)
  126. *
  127. * @return string Unique id
  128. *
  129. * @since 2.0
  130. */
  131. public function getID() {
  132. return spl_object_hash($this);
  133. }
  134. /**
  135. * Get the item parent
  136. *
  137. * @return AppTreeItem The parent item
  138. *
  139. * @since 2.0
  140. */
  141. public function getParent() {
  142. return $this->_parent;
  143. }
  144. /**
  145. * Set the parent item
  146. *
  147. * @param AppTreeItem $item The menu item
  148. *
  149. * @return AppTreeItem $this for chaining support
  150. *
  151. * @since 2.0
  152. */
  153. public function setParent($item) {
  154. $this->_parent = $item;
  155. return $this;
  156. }
  157. /**
  158. * Get the children list
  159. *
  160. * @return array The list of children
  161. *
  162. * @since 2.0
  163. */
  164. public function getChildren() {
  165. return $this->_children;
  166. }
  167. /**
  168. * Check if this item has a particular children
  169. *
  170. * @param string $id The item id to find
  171. * @param boolean $recursive If the search should go also through the children recursively (default: false)
  172. *
  173. * @return boolean True if the item is a children
  174. *
  175. * @since 2.0
  176. */
  177. public function hasChild($id, $recursive = false) {
  178. if (isset($this->_children[$id])) {
  179. return true;
  180. }
  181. if ($recursive) {
  182. foreach ($this->_children as $child) {
  183. if ($child->hasChild($id, $recursive)) return true;
  184. }
  185. }
  186. return false;
  187. }
  188. /**
  189. * Count the children of the item
  190. *
  191. * @return int The number of children
  192. *
  193. * @since 2.0
  194. */
  195. public function hasChildren() {
  196. return count($this->_children);
  197. }
  198. /**
  199. * Add a child to the item
  200. *
  201. * @param AppTreeItem $item The item to add
  202. *
  203. * @return AppTreeItem $this for chaining support
  204. *
  205. * @since 2.0
  206. */
  207. public function addChild(AppTreeItem $item) {
  208. $item->setParent($this);
  209. $this->_children[$item->getID()] = $item;
  210. return $this;
  211. }
  212. /**
  213. * Add a list of items to the item
  214. *
  215. * @param array $children The list of items to add
  216. *
  217. * @return AppTreeItem $this for chaining support
  218. *
  219. * @since 2.0
  220. */
  221. public function addChildren(array $children) {
  222. foreach ($children as $child) {
  223. $this->addChild($child);
  224. }
  225. return $this;
  226. }
  227. /**
  228. * Remove a child
  229. *
  230. * @param AppTreeItem $item The child to remove
  231. *
  232. * @return AppTreeItem $this for chaining support
  233. *
  234. * @since 2.0
  235. */
  236. public function removeChild(AppTreeItem $item) {
  237. $item->setParent(null);
  238. unset($this->_children[$item->getID()]);
  239. return $this;
  240. }
  241. /**
  242. * Remove the item with the given id
  243. *
  244. * @param string $id The id of the item to remove
  245. *
  246. * @return AppTreeItem $this for chaining support
  247. *
  248. * @since 2.0
  249. */
  250. public function removeChildById($id) {
  251. if ($this->hasChild($id)) {
  252. $this->removeChild($this->_children[$id]);
  253. }
  254. return $this;
  255. }
  256. /**
  257. * Get the path from the current item to the root of the tree
  258. *
  259. * @return array The pathway
  260. *
  261. * @since 2.0
  262. */
  263. public function getPathway() {
  264. if ($this->_parent == null) {
  265. return array();
  266. }
  267. $pathway = $this->_parent->getPathway();
  268. $pathway[] = $this;
  269. return $pathway;
  270. }
  271. /**
  272. * Filter all the items recursiveluy
  273. *
  274. * @param function $callback A function to call
  275. * @param array $args A list of arguments to pass
  276. *
  277. * @since 2.0
  278. */
  279. public function filter($callback, $args = array()) {
  280. // call filter function
  281. call_user_func_array($callback, array_merge(array($this), $args));
  282. // filter all children
  283. foreach ($this->getChildren() as $child) {
  284. $child->filter($callback, $args);
  285. }
  286. }
  287. }
  288. /**
  289. * Exception for the AppTree class
  290. *
  291. * @see AppTree
  292. */
  293. class AppTreeException extends AppException {}