16 |
// | Authors: Wolfram Kriesing <wolfram@kriesing.de> | |
// | Authors: Wolfram Kriesing <wolfram@kriesing.de> | |
17 |
// +----------------------------------------------------------------------+ |
// +----------------------------------------------------------------------+ |
18 |
// |
// |
|
// Id: Memory.php,v 1.17 2003/01/18 15:38:04 cain Exp |
|
19 |
// $Id$ |
// $Id$ |
20 |
|
|
21 |
require_once('Tree/Common.php'); |
require_once 'Tree/Common.php'; |
22 |
require_once('Tree/Error.php'); |
require_once 'Tree/Error.php'; |
23 |
|
|
24 |
/** |
/** |
25 |
* this class can be used to step through a tree using ['parent'], ['child'], etc. |
* this class can be used to step through a tree using ['parent'], ['child'], etc. |
145 |
var $_getNodeCurParent; |
var $_getNodeCurParent; |
146 |
|
|
147 |
/** |
/** |
148 |
|
* the maximum depth of the tree |
149 |
|
* @access private |
150 |
|
* @var int the maximum depth of the tree |
151 |
|
*/ |
152 |
|
var $_treeDepth = 0; |
153 |
|
|
154 |
|
/** |
155 |
* set up this object |
* set up this object |
156 |
* |
* |
157 |
* @version 2001/06/27 |
* @version 2001/06/27 |
191 |
* @param array $options additional options you can set |
* @param array $options additional options you can set |
192 |
* @return boolean true on success |
* @return boolean true on success |
193 |
*/ |
*/ |
194 |
function setDataSource( $dsn , $options=array() ) |
function switchDataSource( $type , $dsn='' , $options=array() ) |
195 |
{ |
{ |
196 |
$this->Tree( $dsn , $options ); |
$data = $this->getNode(); |
197 |
|
//$this->Tree( $dsn , $options ); |
198 |
|
$this->Tree_Memory( $type , $GLOBALS['dummy'] , $options ); |
199 |
|
|
200 |
|
// this method prepares data retreived using getNode to be used |
201 |
|
// in this type of tree |
202 |
|
$this->dataSourceClass->setData($data); |
203 |
|
$this->setup(); |
204 |
} |
} |
205 |
|
|
206 |
/** |
/** |
226 |
* @version 2002/01/19 |
* @version 2002/01/19 |
227 |
* @access public |
* @access public |
228 |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
* @author Wolfram Kriesing <wolfram@kriesing.de> |
229 |
|
* @param array the result of a query which retreives (all) the tree data from a source |
230 |
* @return true or Tree_Error |
* @return true or Tree_Error |
231 |
*/ |
*/ |
232 |
function setup() |
function setup($data=null) |
233 |
{ |
{ |
234 |
if( $this->debug ) |
if( $this->debug ) |
235 |
{ |
{ |
237 |
$startTime = $startTime[1]+$startTime[0]; |
$startTime = $startTime[1]+$startTime[0]; |
238 |
} |
} |
239 |
|
|
240 |
if(PEAR::isError($res = $this->dataSourceClass->setup()) ) |
if(PEAR::isError($res = $this->dataSourceClass->setup($data)) ) |
241 |
return $res; |
return $res; |
242 |
|
|
243 |
if( $this->debug ) |
if( $this->debug ) |
252 |
} |
} |
253 |
|
|
254 |
/** |
/** |
255 |
* retreive all the navigation data from the db and call build to build the |
* retreive all the navigation data from the db and build the |
256 |
* tree in the array data and structure |
* tree in the array data and structure |
257 |
* |
* |
258 |
* @version 2001/11/20 |
* @version 2001/11/20 |
398 |
{ |
{ |
399 |
// see comments in 'move' and 'remove' |
// see comments in 'move' and 'remove' |
400 |
|
|
401 |
if( method_exists($this->dataSourceClass,'add') ) |
if (method_exists($this->dataSourceClass,'add')) { |
402 |
return $this->dataSourceClass->add( $newValues , $parentId , $prevId ); |
return $this->dataSourceClass->add( $newValues , $parentId , $prevId ); |
403 |
else |
} else { |
404 |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |
405 |
|
} |
406 |
} // end of function |
} // end of function |
407 |
|
|
408 |
|
|
419 |
{ |
{ |
420 |
// if removing recursively is not allowed, which means every child should be removed |
// if removing recursively is not allowed, which means every child should be removed |
421 |
// then check if this element has a child and return "sorry baby cant remove :-) " |
// then check if this element has a child and return "sorry baby cant remove :-) " |
422 |
if( $this->removeRecursively != true ) |
if ($this->removeRecursively != true) { |
423 |
{ |
if (isset( $this->data[$id]['child'] )) { |
|
if( isset( $this->data[$id]['child'] ) ) |
|
|
{ |
|
424 |
// TODO raise PEAR warning |
// TODO raise PEAR warning |
425 |
return $this->_throwError("Element with id=$id has children, cant be removed. Set 'setRemoveRecursively' to true to allow this.",__LINE__); |
return $this->_throwError("Element with id=$id has children, cant be removed. Set 'setRemoveRecursively' to true to allow this.",__LINE__); |
426 |
} |
} |
430 |
// if the prevId is in use we need to update the prevId of the element after the one that |
// if the prevId is in use we need to update the prevId of the element after the one that |
431 |
// is removed too, to have the prevId of the one that is removed!!! |
// is removed too, to have the prevId of the one that is removed!!! |
432 |
|
|
433 |
if( method_exists($this->dataSourceClass,'add') ) |
if (method_exists($this->dataSourceClass,'remove')) { |
434 |
return $this->dataSourceClass->remove( $id ); |
return $this->dataSourceClass->remove( $id ); |
435 |
else |
} else { |
436 |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |
437 |
|
} |
438 |
} |
} |
439 |
|
|
440 |
/** |
/** |
542 |
// and it has to change the prevId of the element that will be after it |
// and it has to change the prevId of the element that will be after it |
543 |
// so we may be simply call some method like 'update' too? |
// so we may be simply call some method like 'update' too? |
544 |
|
|
545 |
if( method_exists($this->dataSourceClass,'add') ) |
if( method_exists($this->dataSourceClass,'move') ) |
546 |
return $this->dataSourceClass->move( $idToMove , $newParentId , $prevId ); |
return $this->dataSourceClass->move( $idToMove , $newParentId , $prevId ); |
547 |
else |
else |
548 |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |
559 |
*/ |
*/ |
560 |
function update( $id , $data ) |
function update( $id , $data ) |
561 |
{ |
{ |
562 |
if( method_exists($this->dataSourceClass,'add') ) |
if (method_exists($this->dataSourceClass,'update')) { |
563 |
return $this->dataSourceClass->update($id,$data); |
return $this->dataSourceClass->update($id,$data); |
564 |
else |
} else { |
565 |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |
566 |
|
} |
567 |
} // end of function |
} // end of function |
568 |
|
|
569 |
|
|
601 |
// set the level, since we are walking through the structure here anyway we |
// set the level, since we are walking through the structure here anyway we |
602 |
// can do this here, instead of up in the setup method :-) |
// can do this here, instead of up in the setup method :-) |
603 |
// always set the level to one higher than the parent's level, easy ha? |
// always set the level to one higher than the parent's level, easy ha? |
604 |
if( isset($this->data[$parentId]['parent']['level']) ) // this applies only to the root element(s) |
if (isset($this->data[$parentId]['parent']['level'])) { // this applies only to the root element(s) |
605 |
$this->data[$parentId]['level'] = $this->data[$parentId]['parent']['level']+1; |
$this->data[$parentId]['level'] = $this->data[$parentId]['parent']['level']+1; |
606 |
else |
|
607 |
|
if ($this->data[$parentId]['level']>$this->_treeDepth) { |
608 |
|
$this->_treeDepth = $this->data[$parentId]['level']; |
609 |
|
} |
610 |
|
} else { |
611 |
$this->data[$parentId]['level'] = 0; // set first level number to 0 |
$this->data[$parentId]['level'] = 0; // set first level number to 0 |
612 |
|
} |
613 |
|
|
614 |
if( isset($this->children[$parentId]) && sizeof($this->children[$parentId]) ) |
if (isset($this->children[$parentId]) && sizeof($this->children[$parentId])) { |
|
{ |
|
615 |
// go thru all the folders |
// go thru all the folders |
616 |
foreach( $this->children[$parentId] as $child ) |
foreach ($this->children[$parentId] as $child) { |
|
{ |
|
617 |
// build the structure under this folder, |
// build the structure under this folder, |
618 |
// use the current folder as the new parent and call build recursively |
// use the current folder as the new parent and call build recursively |
619 |
// to build all the children |
// to build all the children |
644 |
function walk( $walkFunction , $id=0 , $returnType='string') |
function walk( $walkFunction , $id=0 , $returnType='string') |
645 |
{ |
{ |
646 |
$useNode = $this->structure; // by default all of structure is used |
$useNode = $this->structure; // by default all of structure is used |
647 |
if( $id == 0 ) |
if ($id == 0) { |
|
{ |
|
648 |
$keys = array_keys($this->structure); |
$keys = array_keys($this->structure); |
649 |
$id = $keys[0]; |
$id = $keys[0]; |
650 |
} |
} else { |
|
else |
|
|
{ |
|
651 |
$path = $this->getPath($id); // get the path, to be able to go to the element in this->structure |
$path = $this->getPath($id); // get the path, to be able to go to the element in this->structure |
652 |
array_pop($path); // pop off the last element, since it is the one requested |
array_pop($path); // pop off the last element, since it is the one requested |
653 |
$curNode = $this->structure; // start at the root of structure |
$curNode = $this->structure; // start at the root of structure |
654 |
foreach( $path as $node ) |
foreach ($path as $node) { |
|
{ |
|
655 |
$curNode = $curNode[$node['id']]; // go as deep into structure as path defines |
$curNode = $curNode[$node['id']]; // go as deep into structure as path defines |
656 |
} |
} |
|
|
|
657 |
$useNode = array(); // empty it first, so we dont have the other stuff in there from before |
$useNode = array(); // empty it first, so we dont have the other stuff in there from before |
658 |
$useNode[$id] = $curNode[$id]; // copy only the branch of the tree that the parameter $id requested |
$useNode[$id] = $curNode[$id]; // copy only the branch of the tree that the parameter $id requested |
659 |
} |
} |
679 |
*/ |
*/ |
680 |
function _walk( $walkFunction , &$curLevel , $returnType ) |
function _walk( $walkFunction , &$curLevel , $returnType ) |
681 |
{ |
{ |
682 |
if( sizeof($curLevel) ) |
if (sizeof($curLevel)) { |
683 |
{ |
foreach ($curLevel as $key=>$value) { |
|
foreach( $curLevel as $key=>$value ) |
|
|
{ |
|
684 |
$ret = call_user_func( $walkFunction , $this->data[$key] ); |
$ret = call_user_func( $walkFunction , $this->data[$key] ); |
685 |
|
switch ($returnType) { |
|
switch( $returnType ) |
|
|
{ |
|
686 |
case 'array': $this->walkReturn[] = $ret; |
case 'array': $this->walkReturn[] = $ret; |
687 |
break; |
break; |
688 |
case 'ifArray': // this only adds the element if the $ret is an array and contains data |
case 'ifArray': // this only adds the element if the $ret is an array and contains data |
689 |
if( is_array($ret) ) |
if (is_array($ret)) { |
690 |
$this->walkReturn[] = $ret; |
$this->walkReturn[] = $ret; |
691 |
|
} |
692 |
break; |
break; |
693 |
default: $this->walkReturn.= $ret; |
default: $this->walkReturn.= $ret; |
694 |
break; |
break; |
1146 |
*/ |
*/ |
1147 |
function &getNode( $startId=0 , $depth=0 ) |
function &getNode( $startId=0 , $depth=0 ) |
1148 |
{ |
{ |
1149 |
if( $startId == 0) |
if ($startId == 0) { |
|
{ |
|
1150 |
$level = 0; |
$level = 0; |
1151 |
} |
} else { |
|
else |
|
|
{ |
|
1152 |
$level = $this->getLevel($startId); |
$level = $this->getLevel($startId); |
1153 |
} |
} |
1154 |
|
|
1156 |
//!!! $this->_getNodeCurParent = $this->data['parent']['id']; |
//!!! $this->_getNodeCurParent = $this->data['parent']['id']; |
1157 |
|
|
1158 |
// if the tree is empty dont walk through it |
// if the tree is empty dont walk through it |
1159 |
if( !sizeof($this->data) ) |
if (!sizeof($this->data)) { |
1160 |
return; |
return; |
1161 |
|
} |
1162 |
|
|
1163 |
return $this->walk( array(&$this,'_getNode') , $startId , 'ifArray' ); |
$ret = $this->walk( array(&$this,'_getNode') , $startId , 'ifArray' ); |
1164 |
|
return $ret; |
1165 |
} // end of function |
} // end of function |
1166 |
|
|
1167 |
/** |
/** |
1179 |
*/ |
*/ |
1180 |
function &_getNode( &$node ) |
function &_getNode( &$node ) |
1181 |
{ |
{ |
1182 |
if( $this->_getNodeMaxLevel ) |
if ($this->_getNodeMaxLevel) { |
1183 |
{ |
if ($this->getLevel($node['id']) < $this->_getNodeMaxLevel) { |
|
if( $this->getLevel($node['id']) < $this->_getNodeMaxLevel ) |
|
1184 |
return $node; |
return $node; |
1185 |
|
} |
1186 |
return; |
return; |
1187 |
} |
} |
1188 |
return $node; |
return $node; |
1215 |
* @return boolean true if the node has children |
* @return boolean true if the node has children |
1216 |
*/ |
*/ |
1217 |
function getChildren( $ids , $levels=1 ) |
function getChildren( $ids , $levels=1 ) |
1218 |
{ |
{ |
1219 |
//FIXXME $levels to be implemented |
//FIXXME $levels to be implemented |
1220 |
$ret = array(); |
$ret = array(); |
1221 |
if( is_array($ids) ) |
if (is_array($ids)) { |
1222 |
{ |
foreach ($ids as $aId) { |
1223 |
foreach( $ids as $aId ) |
if ($this->hasChildren( $aId )) { |
|
{ |
|
|
if( $this->hasChildren( $aId ) ) |
|
1224 |
$ret[$aId] = $this->data[$aId]['children']; |
$ret[$aId] = $this->data[$aId]['children']; |
1225 |
|
} |
1226 |
} |
} |
1227 |
|
|
1228 |
} |
} else { |
1229 |
else |
if ($this->hasChildren( $ids )) { |
|
{ |
|
|
if( $this->hasChildren( $ids ) ) |
|
1230 |
$ret = $this->data[$ids]['children']; |
$ret = $this->data[$ids]['children']; |
1231 |
|
} |
1232 |
} |
} |
1233 |
return $ret; |
return $ret; |
1234 |
} // end of function |
} // end of function |
1267 |
|
|
1268 |
// if $node is an array, we assume it is a collection of elements |
// if $node is an array, we assume it is a collection of elements |
1269 |
if( !is_array($node) ) |
if( !is_array($node) ) |
1270 |
$node = $this->getNode($node); // if $node==0 then the entire tree is retreived |
$nodes = $this->getNode($node); // if $node==0 then the entire tree is retreived |
1271 |
|
|
1272 |
foreach( $node as $aNode ) |
if (sizeof($node)) { |
1273 |
{ |
print '<table border="1"><tr><th>name</th>'; |
1274 |
print '<u>Element</u> :'; |
$keys = array(); |
1275 |
foreach( $aNode as $key=>$aElement ) |
foreach ($this->getRoot() as $key=>$x) { |
1276 |
{ |
if (!is_array($x)) { |
1277 |
print "$key"; |
print "<th>$key</th>"; |
1278 |
|
$keys[] = $key; |
|
if( in_array( $key , $dontDump ) ) |
|
|
{ |
|
|
if( !isset($aElement['id']) && is_array($aElement) ) |
|
|
{ |
|
|
print "['ids']="; |
|
|
$ids = array(); |
|
|
foreach( $aElement as $aSubElement ) |
|
|
$ids[] = $aSubElement['id']; |
|
|
print implode(', ',$ids); |
|
|
} |
|
|
else |
|
|
|
|
|
print "['id']=".$aElement['id']; |
|
|
} |
|
|
else |
|
|
{ |
|
|
print '='; |
|
|
print_r($aElement); |
|
1279 |
} |
} |
|
print " ... "; |
|
1280 |
} |
} |
1281 |
print "<br>\n"; |
print "</tr>"; |
1282 |
} |
|
1283 |
|
foreach ($nodes as $aNode) { |
1284 |
|
print '<tr><td nowrap="nowrap">'; |
1285 |
|
$prefix = ''; |
1286 |
|
for($i=0;$i<$aNode['level'];$i++) $prefix .= '- '; |
1287 |
|
print "$prefix {$aNode['name']}</td>"; |
1288 |
|
foreach ($keys as $aKey) { |
1289 |
|
if (!is_array($key)) { |
1290 |
|
$val = $aNode[$aKey] ? $aNode[$aKey] : ' '; |
1291 |
|
print "<td>$val</td>"; |
1292 |
|
} |
1293 |
|
} |
1294 |
|
print "</tr>"; |
1295 |
|
} |
1296 |
|
print "</table>"; |
1297 |
|
} |
1298 |
} // end of function |
} // end of function |
1299 |
|
|
1300 |
|
|
1319 |
*/ |
*/ |
1320 |
function copy( $srcId , $destId ) |
function copy( $srcId , $destId ) |
1321 |
{ |
{ |
1322 |
if( method_exists($this->dataSourceClass,'add') ) |
if( method_exists($this->dataSourceClass,'copy') ) |
1323 |
return $this->dataSourceClass->copy( $srcId , $destId ); |
return $this->dataSourceClass->copy( $srcId , $destId ); |
1324 |
else |
else |
1325 |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |
return $this->_throwError( 'method not implemented yet.' , __LINE__ ); |