1 |
<?php |
2 |
// |
3 |
// +----------------------------------------------------------------------+ |
4 |
// | PHP Version 4 | |
5 |
// +----------------------------------------------------------------------+ |
6 |
// | Copyright (c) 1997-2003 The PHP Group | |
7 |
// +----------------------------------------------------------------------+ |
8 |
// | This source file is subject to version 2.02 of the PHP license, | |
9 |
// | that is bundled with this package in the file LICENSE, and is | |
10 |
// | available at through the world-wide-web at | |
11 |
// | http://www.php.net/license/2_02.txt. | |
12 |
// | If you did not receive a copy of the PHP license and are unable to | |
13 |
// | obtain it through the world-wide-web, please send a note to | |
14 |
// | license@php.net so we can mail you a copy immediately. | |
15 |
// +----------------------------------------------------------------------+ |
16 |
// | Authors: Wolfram Kriesing <wolfram@kriesing.de> | |
17 |
// +----------------------------------------------------------------------+ |
18 |
// |
19 |
// Id: Common.php,v 1.17 2003/01/28 19:18:37 cain Exp |
20 |
// $Id: Common.php,v 1.17 2003/01/28 19:18:37 cain Exp $ |
21 |
|
22 |
require_once('Tree/OptionsDB.php'); |
23 |
|
24 |
define("TREE_ERROR", -1); |
25 |
define("TREE_ERROR_INVALID_PARENT", -2); |
26 |
|
27 |
/** |
28 |
* common tree class, implements common functionality |
29 |
* |
30 |
* this class extends Tree_OptionsDB so every class that extends this oe can |
31 |
* connect to a db and set options |
32 |
* |
33 |
* @access public |
34 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
35 |
* @version 2001/06/27 |
36 |
* @package Tree |
37 |
*/ |
38 |
class Tree_Common extends Tree_OptionsDB |
39 |
{ |
40 |
|
41 |
/** |
42 |
* put proper value-keys are given in each class, depending on the implementation |
43 |
* only some options are needed or allowed, see the classes which extend this one |
44 |
* |
45 |
* @access public |
46 |
* @var array saves the options passed to the constructor |
47 |
*/ |
48 |
var $options = array(); |
49 |
|
50 |
|
51 |
/** |
52 |
* |
53 |
* |
54 |
* @version 2002/01/18 |
55 |
* @access public |
56 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
57 |
*/ |
58 |
function getChildId( $id ) |
59 |
{ |
60 |
$child = $this->getChild( $id ); |
61 |
return $child['id']; |
62 |
} |
63 |
|
64 |
/** |
65 |
* get the ids of the children of the given element |
66 |
* |
67 |
* @version 2002/02/06 |
68 |
* @access public |
69 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
70 |
* @param integer $id ID of the element that the children shall be retreived for |
71 |
* @return mixed an array of all the ids of the children of the element with id=$id, |
72 |
* or false if there are no children |
73 |
*/ |
74 |
function getChildrenIds( $id ) |
75 |
{ |
76 |
if( !($children = $this->getChildren( $id )) ) // returns false if no children exist |
77 |
return array(); // return an empty array, if you want to know if there are children, use hasChildren |
78 |
|
79 |
if( $children && sizeof($children) ) |
80 |
{ |
81 |
foreach( $children as $aChild ) |
82 |
$childrenIds[] = $aChild['id']; |
83 |
} |
84 |
|
85 |
return $childrenIds; |
86 |
} |
87 |
|
88 |
/** |
89 |
* gets all the children and grand children etc. |
90 |
* |
91 |
* @version 2002/09/30 |
92 |
* @access public |
93 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
94 |
* @param integer $id ID of the element that the children shall be retreived for |
95 |
* @return mixed an array of all the children of the element with id=$id, |
96 |
* or false if there are no children |
97 |
*/ |
98 |
function getAllChildren( $id ) |
99 |
{ |
100 |
$retChildren = false; |
101 |
if( $children = $this->hasChildren( $id ) ) |
102 |
{ |
103 |
$retChildren = $this->_getAllChildren( $id ); |
104 |
} |
105 |
return $retChildren; |
106 |
} |
107 |
|
108 |
/** |
109 |
* this method gets all the children recursively |
110 |
* |
111 |
* @see getAllChildren() |
112 |
* @version 2002/09/30 |
113 |
* @access public |
114 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
115 |
* @param integer $id ID of the element that the children shall be retreived for |
116 |
* @return mixed an array of all the ids of the children of the element with id=$id, |
117 |
* or false if there are no children |
118 |
*/ |
119 |
function &_getAllChildren( $id ) |
120 |
{ |
121 |
$retChildren = array(); |
122 |
if( $children = $this->getChildren( $id ) ) |
123 |
{ |
124 |
foreach( $children as $key=>$aChild ) |
125 |
{ |
126 |
$retChildren[] = &$children[$key]; |
127 |
$retChildren = array_merge($retChildren,$this->_getAllChildren( $aChild['id'] )); |
128 |
} |
129 |
} |
130 |
return $retChildren; |
131 |
} |
132 |
|
133 |
/** |
134 |
* gets all the children-ids and grand children-ids |
135 |
* |
136 |
* @version 2002/09/30 |
137 |
* @access public |
138 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
139 |
* @param integer $id ID of the element that the children shall be retreived for |
140 |
* @return mixed an array of all the ids of the children of the element with id=$id, |
141 |
* or false if there are no children |
142 |
*/ |
143 |
function getAllChildrenIds( $id ) |
144 |
{ |
145 |
$childrenIds = array(); |
146 |
if( $allChildren = $this->getAllChildren($id) ) |
147 |
{ |
148 |
$childrenIds = array(); |
149 |
foreach( $allChildren as $aNode ) |
150 |
$childrenIds[] = $aNode['id']; |
151 |
} |
152 |
return $childrenIds; |
153 |
} |
154 |
/** |
155 |
* get the id of the parent for the given element |
156 |
* |
157 |
* @version 2002/01/18 |
158 |
* @access public |
159 |
* @param integer $id the id of the element for which the parentId shall be retreived |
160 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
161 |
*/ |
162 |
function getParentId( $id ) |
163 |
{ |
164 |
$parent = $this->getParent( $id ); |
165 |
return $parent['id']; |
166 |
} |
167 |
|
168 |
/** |
169 |
* this gets all the preceeding nodes, the parent and it's parent and so on |
170 |
* |
171 |
* @version 2002/08/19 |
172 |
* @access public |
173 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
174 |
* @param integer $id the id of the element for which the parentId shall be retreived |
175 |
* @return array of the parent nodes including the node with id $id |
176 |
*/ |
177 |
function getParents( $id ) |
178 |
{ |
179 |
$path = $this->getPath($id); |
180 |
$parents = array(); |
181 |
if( sizeof($path) ) |
182 |
foreach( $path as $aNode ) |
183 |
$parents[] = $aNode; |
184 |
return $parents; |
185 |
} |
186 |
|
187 |
/** |
188 |
* get the ids of the parents and all it's parents and so on |
189 |
* it simply returns the ids of the elements returned by getParents() |
190 |
|
191 |
* @see getParents() |
192 |
* @version 2002/08/19 |
193 |
* @access public |
194 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
195 |
* @param integer $id the id of the element for which the parentId shall be retreived |
196 |
* @return array of the ids |
197 |
*/ |
198 |
function getParentsIds( $id ) |
199 |
{ |
200 |
$parents = $this->getParents($id); |
201 |
$parentsIds = array(); |
202 |
if( sizeof($parents) ) |
203 |
foreach( $parents as $aNode ) |
204 |
$parentsIds[] = $aNode['id']; |
205 |
return $parentsIds; |
206 |
} |
207 |
|
208 |
/** |
209 |
* |
210 |
* |
211 |
* @version 2002/01/18 |
212 |
* @access public |
213 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
214 |
*/ |
215 |
function getNextId( $id ) |
216 |
{ |
217 |
$next = $this->getNext( $id ); |
218 |
return $next['id']; |
219 |
} |
220 |
|
221 |
/** |
222 |
* |
223 |
* |
224 |
* @version 2002/01/18 |
225 |
* @access public |
226 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
227 |
*/ |
228 |
function getPreviousId( $id ) |
229 |
{ |
230 |
$previous = $this->getPrevious( $id ); |
231 |
return $previous['id']; |
232 |
} |
233 |
|
234 |
/** |
235 |
* |
236 |
* |
237 |
* @version 2002/01/18 |
238 |
* @access public |
239 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
240 |
*/ |
241 |
function getLeftId( $id ) |
242 |
{ |
243 |
$left = $this->getLeft( $id ); |
244 |
return $left['id']; |
245 |
} |
246 |
|
247 |
/** |
248 |
* |
249 |
* |
250 |
* @version 2002/01/18 |
251 |
* @access public |
252 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
253 |
*/ |
254 |
function getRightId( $id ) |
255 |
{ |
256 |
$right = $this->getRight( $id ); |
257 |
return $right['id']; |
258 |
} |
259 |
|
260 |
/** |
261 |
* |
262 |
* |
263 |
* @version 2002/01/18 |
264 |
* @access public |
265 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
266 |
*/ |
267 |
function getFirstRootId() |
268 |
{ |
269 |
$firstRoot = $this->getFirstRoot(); |
270 |
return $firstRoot['id']; |
271 |
} |
272 |
|
273 |
/** |
274 |
* |
275 |
* |
276 |
* @version 2002/04/16 |
277 |
* @access public |
278 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
279 |
*/ |
280 |
function getRootId() |
281 |
{ |
282 |
$firstRoot = $this->getRoot(); |
283 |
return $firstRoot['id']; |
284 |
} |
285 |
|
286 |
/** |
287 |
* returns the path as a string |
288 |
* |
289 |
* @access public |
290 |
* @version 2002/03/28 |
291 |
* @access public |
292 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
293 |
* @param mixed $id the id of the node to get the path for |
294 |
* @return array this array contains all elements from the root to the element given by the id |
295 |
* |
296 |
*/ |
297 |
function getPathAsString( $id , $seperator='/' ) |
298 |
{ |
299 |
$path = $this->getPath($id); |
300 |
foreach( $path as $aNode ) |
301 |
$pathArray[] = $aNode['name']; |
302 |
|
303 |
$pathString = ''; |
304 |
if( sizeof($pathArray) ) |
305 |
$pathString = implode($seperator,$pathArray); |
306 |
return $pathString; |
307 |
} // end of function |
308 |
|
309 |
|
310 |
|
311 |
|
312 |
|
313 |
|
314 |
// |
315 |
// abstract methods, those should be overwritten by the implementing class |
316 |
// |
317 |
|
318 |
|
319 |
/** |
320 |
* gets the path to the element given by its id |
321 |
* |
322 |
* @abstract |
323 |
* @version 2001/10/10 |
324 |
* @access public |
325 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
326 |
* @param mixed $id the id of the node to get the path for |
327 |
* @return array this array contains all elements from the root to the element given by the id |
328 |
* |
329 |
*/ |
330 |
function getPath( $id ) |
331 |
{ |
332 |
return $this->_throwError( 'not implemented, at least not overwritten the abstract declaration' , __LINE__ ); |
333 |
} // end of function |
334 |
|
335 |
/** |
336 |
* get the level, which is how far below the root the element with the given id is |
337 |
* |
338 |
* @abstract |
339 |
* @version 2001/11/25 |
340 |
* @access public |
341 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
342 |
* @param mixed $id the id of the node to get the level for |
343 |
* |
344 |
*/ |
345 |
function getLevel( $id ) |
346 |
{ |
347 |
return $this->_throwError( 'not implemented, at least not overwritten the abstract declaration' , __LINE__ ); |
348 |
} // end of function |
349 |
|
350 |
/** |
351 |
* returns if $childId is a child of $id |
352 |
* |
353 |
* @abstract |
354 |
* @version 2002/04/29 |
355 |
* @access public |
356 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
357 |
* @param int id of the element |
358 |
* @param int id of the element to check if it is a child |
359 |
* @param boolean if this is true the entire tree below is checked |
360 |
* @return boolean true if it is a child |
361 |
*/ |
362 |
function isChildOf( $id , $childId , $checkAll=true ) |
363 |
{ |
364 |
return $this->_throwError( 'not implemented, at least not overwritten the abstract declaration' , __LINE__ ); |
365 |
} // end of function |
366 |
|
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
// |
373 |
// PRIVATE METHODS |
374 |
// |
375 |
|
376 |
|
377 |
/** |
378 |
* prepare multiple results |
379 |
* |
380 |
* @see _prepareResult() |
381 |
* @access private |
382 |
* @version 2002/03/03 |
383 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
384 |
* @param |
385 |
* @return |
386 |
*/ |
387 |
function _prepareResults( $results ) |
388 |
{ |
389 |
$newResults = array(); |
390 |
foreach( $results as $key=>$aResult ) |
391 |
$newResults[$key] = $this->_prepareResult($aResult); |
392 |
return $newResults; |
393 |
} |
394 |
|
395 |
/** |
396 |
* map back the index names to get what is expected |
397 |
* |
398 |
* @access private |
399 |
* @version 2002/03/03 |
400 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
401 |
* @param |
402 |
* @return |
403 |
*/ |
404 |
function _prepareResult( $result ) |
405 |
{ |
406 |
$map = $this->getOption('columnNameMaps'); |
407 |
|
408 |
if( $map ) |
409 |
foreach( $map as $key=>$columnName ) |
410 |
{ |
411 |
$result[$key] = $result[$columnName]; |
412 |
unset($result[$columnName]); |
413 |
} |
414 |
return $result; |
415 |
} |
416 |
|
417 |
/** |
418 |
* this method retreives the real column name, as used in the DB |
419 |
* since the internal names are fixed, to be portable between different |
420 |
* DB-column namings, we map the internal name to the real column name here |
421 |
* |
422 |
* @access private |
423 |
* @version 2002/03/02 |
424 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
425 |
* @param |
426 |
* @return |
427 |
*/ |
428 |
function _getColName( $internalName ) |
429 |
{ |
430 |
if( $map = $this->getOption( 'columnNameMaps' ) ) |
431 |
{ |
432 |
if( isset($map[$internalName]) ) |
433 |
return $map[$internalName]; |
434 |
} |
435 |
return $internalName; |
436 |
} |
437 |
|
438 |
/** |
439 |
* |
440 |
* |
441 |
* @access private |
442 |
* @version 2002/03/02 |
443 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
444 |
* @param |
445 |
* @return |
446 |
*/ |
447 |
function _throwError( $msg , $line , $mode=null ) |
448 |
{ |
449 |
if( $mode===null && $this->debug>0 ) |
450 |
$mode = PEAR_ERROR_PRINT; |
451 |
return new Tree_Error( $msg , $line , __FILE__ , $mode , $this->dbh->last_query ); |
452 |
} |
453 |
|
454 |
} |
455 |
?> |