PageRenderTime 39ms CodeModel.GetById 15ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

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