16 |
// | Authors: | |
// | Authors: | |
17 |
// +----------------------------------------------------------------------+ |
// +----------------------------------------------------------------------+ |
18 |
// |
// |
|
// Id: DBnested.php,v 1.13 2003/01/18 15:35:47 cain Exp |
|
19 |
// $Id$ |
// $Id$ |
20 |
|
|
21 |
require_once('Tree/Common.php'); |
require_once('Tree/Common.php'); |
389 |
function _move( $idToMove , $newParentId , $newPrevId=0 ) |
function _move( $idToMove , $newParentId , $newPrevId=0 ) |
390 |
{ |
{ |
391 |
// do some integrity checks first |
// do some integrity checks first |
392 |
if( $newPrevId ) |
if ($newPrevId) { |
393 |
{ |
if ($newPrevId==$idToMove) { // dont let people move an element behind itself, tell it succeeded, since it already is there :-) |
|
if( $newPrevId == $idToMove ) // dont let people move an element behind itself, tell it succeeded, since it already is there :-) |
|
|
{ |
|
394 |
return true; |
return true; |
395 |
} |
} |
396 |
if( PEAR::isError($newPrevious = $this->getElement( $newPrevId )) ) |
if (PEAR::isError($newPrevious=$this->getElement($newPrevId))) { |
397 |
return $newPrevious; |
return $newPrevious; |
398 |
|
} |
399 |
$newParentId = $newPrevious['parentId']; |
$newParentId = $newPrevious['parentId']; |
400 |
} |
} else { |
401 |
else |
if ($newParentId==0) { |
|
{ |
|
|
if( $newParentId == 0 ) |
|
|
{ |
|
402 |
return $this->_throwError( 'no parent id given' , __LINE__ ); |
return $this->_throwError( 'no parent id given' , __LINE__ ); |
403 |
} |
} |
404 |
if( $this->isChildOf( $idToMove , $newParentId ) ) // if the element shall be moved under one of its children, return false |
if ($this->isChildOf($idToMove,$newParentId)) { // if the element shall be moved under one of its children, return false |
|
{ |
|
405 |
return $this->_throwError( 'can not move an element under one of its children' , __LINE__ ); |
return $this->_throwError( 'can not move an element under one of its children' , __LINE__ ); |
406 |
} |
} |
407 |
if( $newParentId == $idToMove ) // dont do anything to let an element be moved under itself, which is bullshit |
if ($newParentId==$idToMove) { // dont do anything to let an element be moved under itself, which is bullshit |
|
{ |
|
408 |
return true; |
return true; |
409 |
} |
} |
410 |
if( PEAR::isError($newParent = $this->getElement( $newParentId )) ) // try to retreive the data of the parent element |
if (PEAR::isError($newParent=$this->getElement($newParentId))) { // try to retreive the data of the parent element |
|
{ |
|
411 |
return $newParent; |
return $newParent; |
412 |
} |
} |
413 |
} |
} |
414 |
|
|
415 |
if( PEAR::isError($element=$this->getElement($idToMove)) ) // get the data of the element itself |
if (PEAR::isError($element=$this->getElement($idToMove))) { // get the data of the element itself |
|
{ |
|
416 |
return $element; |
return $element; |
417 |
} |
} |
418 |
|
|
422 |
// FIXXME start transaction |
// FIXXME start transaction |
423 |
|
|
424 |
// add the left/right values in the new parent, to have the space to move the new values in |
// add the left/right values in the new parent, to have the space to move the new values in |
425 |
if( PEAR::isError($err=$this->_add( $prevVisited , $numberOfElements )) ) |
if (PEAR::isError($err=$this->_add( $prevVisited , $numberOfElements ))) { |
|
{ |
|
426 |
// FIXXME rollback |
// FIXXME rollback |
427 |
//$this->dbh->rollback(); |
//$this->dbh->rollback(); |
428 |
return $err; |
return $err; |
429 |
} |
} |
430 |
|
|
431 |
// update the parentId of the element with $idToMove |
// update the parentId of the element with $idToMove |
432 |
if( PEAR::isError($err=$this->update( $idToMove , array('parentId'=>$newParentId) )) ) |
if (PEAR::isError($err=$this->update($idToMove,array('parentId'=>$newParentId)))) { |
|
{ |
|
433 |
// FIXXME rollback |
// FIXXME rollback |
434 |
//$this->dbh->rollback(); |
//$this->dbh->rollback(); |
435 |
return $err; |
return $err; |
441 |
// if $newPrevId is given we need to get the right value, otherwise the left |
// if $newPrevId is given we need to get the right value, otherwise the left |
442 |
// since the left/right has changed, because we already updated it up there we need to |
// since the left/right has changed, because we already updated it up there we need to |
443 |
// get them again, we have to do that anyway, to have the proper new left/right values |
// get them again, we have to do that anyway, to have the proper new left/right values |
444 |
if( $newPrevId ) |
if ($newPrevId) { |
445 |
{ |
if (PEAR::isError($temp = $this->getElement( $newPrevId ))) { |
|
if( PEAR::isError($temp = $this->getElement( $newPrevId )) ) |
|
|
{ |
|
446 |
// FIXXME rollback |
// FIXXME rollback |
447 |
//$this->dbh->rollback(); |
//$this->dbh->rollback(); |
448 |
return $temp; |
return $temp; |
449 |
} |
} |
450 |
$calcWith = $temp['right']; |
$calcWith = $temp['right']; |
451 |
} |
} else { |
452 |
else |
if (PEAR::isError($temp=$this->getElement($newParentId))) { |
|
{ |
|
|
if( PEAR::isError($temp = $this->getElement( $newParentId )) ) |
|
|
{ |
|
453 |
// FIXXME rollback |
// FIXXME rollback |
454 |
//$this->dbh->rollback(); |
//$this->dbh->rollback(); |
455 |
return $temp; |
return $temp; |
458 |
} |
} |
459 |
|
|
460 |
// get the element that shall be moved again, since the left and right might have changed by the add-call |
// get the element that shall be moved again, since the left and right might have changed by the add-call |
461 |
if( PEAR::isError($element=$this->getElement($idToMove)) ) |
if (PEAR::isError($element=$this->getElement($idToMove))) { |
|
{ |
|
462 |
return $element; |
return $element; |
463 |
} |
} |
464 |
|
|
474 |
$this->_getWhereAddOn(), |
$this->_getWhereAddOn(), |
475 |
$lName,$element['left']-1, |
$lName,$element['left']-1, |
476 |
$rName,$element['right']+1 ); |
$rName,$element['right']+1 ); |
477 |
if( DB::isError( $res = $this->dbh->query($query) ) ) |
if (DB::isError($res=$this->dbh->query($query))) { |
|
{ |
|
478 |
// FIXXME rollback |
// FIXXME rollback |
479 |
//$this->dbh->rollback(); |
//$this->dbh->rollback(); |
480 |
return $this->_throwError( $res->getMessage() , __LINE__ ); |
return $this->_throwError( $res->getMessage() , __LINE__ ); |
481 |
} |
} |
482 |
|
|
483 |
// remove the part of the tree where the element(s) was/were before |
// remove the part of the tree where the element(s) was/were before |
484 |
if( PEAR::isError($err=$this->_remove( $element )) ) |
if (PEAR::isError($err=$this->_remove($element))) { |
|
{ |
|
485 |
// FIXXME rollback |
// FIXXME rollback |
486 |
//$this->dbh->rollback(); |
//$this->dbh->rollback(); |
487 |
return $err; |
return $err; |
501 |
* @param array the new values, the index is the col name |
* @param array the new values, the index is the col name |
502 |
* @return mixed either true or an Tree_Error |
* @return mixed either true or an Tree_Error |
503 |
*/ |
*/ |
504 |
function update( $id , $newValues ) |
function update($id,$newValues) |
505 |
{ |
{ |
506 |
// jsut to be sure nothing gets screwed up :-) |
// jsut to be sure nothing gets screwed up :-) |
507 |
unset( $newValues[$this->_getColName('left')] ); |
unset($newValues[$this->_getColName('left')]); |
508 |
unset( $newValues[$this->_getColName('right')] ); |
unset($newValues[$this->_getColName('right')]); |
509 |
unset( $newValues[$this->_getColName('parentId')] ); |
unset($newValues[$this->_getColName('parentId')]); |
510 |
|
|
511 |
// updating _one_ element in the tree |
// updating _one_ element in the tree |
512 |
$values = array(); |
$values = array(); |
513 |
foreach( $newValues as $key=>$value ) |
foreach ($newValues as $key=>$value) { |
514 |
$values[] = $this->_getColName($key).'='.$this->dbh->quote($value); |
$values[] = $this->_getColName($key).'='.$this->dbh->quote($value); |
515 |
|
} |
|
|
|
516 |
$query = sprintf( 'UPDATE %s SET %s WHERE%s %s=%s', |
$query = sprintf( 'UPDATE %s SET %s WHERE%s %s=%s', |
517 |
$this->table, |
$this->table, |
518 |
implode(',',$values), |
implode(',',$values), |
519 |
$this->_getWhereAddOn(), |
$this->_getWhereAddOn(), |
520 |
$this->_getColName('id'), |
$this->_getColName('id'), |
521 |
$id); |
$id); |
522 |
if( DB::isError( $res=$this->dbh->query($query) ) ){ |
if (DB::isError( $res=$this->dbh->query($query))) { |
523 |
// FIXXME raise PEAR error |
// FIXXME raise PEAR error |
524 |
return $this->_throwError( $res->getMessage() , __LINE__ ); |
return $this->_throwError( $res->getMessage() , __LINE__ ); |
525 |
} |
} |
601 |
* @param |
* @param |
602 |
* @return mixed either the data of the requested element or an Tree_Error |
* @return mixed either the data of the requested element or an Tree_Error |
603 |
*/ |
*/ |
604 |
function getChild( $id ) |
function getChild($id) |
605 |
{ |
{ |
606 |
// subqueries would be cool :-) |
// subqueries would be cool :-) |
607 |
$curElement = $this->getElement( $id ); |
$curElement = $this->getElement( $id ); |
608 |
if( PEAR::isError($curElement) ) |
if (PEAR::isError($curElement)) { |
609 |
return $curElement; |
return $curElement; |
610 |
|
} |
611 |
|
|
612 |
$query = sprintf( 'SELECT * FROM %s WHERE%s %s=%s', |
$query = sprintf( 'SELECT * FROM %s WHERE%s %s=%s', |
613 |
$this->table, |
$this->table, |
614 |
$this->_getWhereAddOn(), |
$this->_getWhereAddOn(), |
615 |
$this->_getColName('left'), |
$this->_getColName('left'), |
616 |
$curElement['left']+1 ); |
$curElement['left']+1 ); |
617 |
if( DB::isError( $res = $this->dbh->getRow($query) ) ) |
if (DB::isError( $res = $this->dbh->getRow($query))) { |
|
{ |
|
618 |
return $this->_throwError( $res->getMessage() , __LINE__ ); |
return $this->_throwError( $res->getMessage() , __LINE__ ); |
619 |
} |
} |
620 |
return $this->_prepareResult( $res ); |
return $this->_prepareResult( $res ); |
645 |
$this->_getColName('right'), |
$this->_getColName('right'), |
646 |
$curElement['right'], |
$curElement['right'], |
647 |
$this->_getColName('left') ); |
$this->_getColName('left') ); |
648 |
if( DB::isError( $res = $this->dbh->getAll($query) ) ) |
if (DB::isError( $res = $this->dbh->getAll($query))) { |
|
{ |
|
649 |
return $this->_throwError( $res->getMessage() , __LINE__ ); |
return $this->_throwError( $res->getMessage() , __LINE__ ); |
650 |
} |
} |
651 |
return $this->_prepareResults( $res ); |
return $this->_prepareResults( $res ); |
747 |
* @return mixed the array with the data of all children |
* @return mixed the array with the data of all children |
748 |
* or false, if there are none |
* or false, if there are none |
749 |
*/ |
*/ |
750 |
function getChildren( $ids , $levels=1 ) |
function getChildren($ids,$levels=1) |
751 |
{ |
{ |
752 |
$res = array(); |
$res = array(); |
753 |
for( $i=1 ; $i<$levels+1 ; $i++ ) |
for( $i=1 ; $i<$levels+1 ; $i++ ) |
767 |
// if no 'order'-option is given |
// if no 'order'-option is given |
768 |
$this->getOption('order') ? $this->getOption('order') : $this->_getColName('left') |
$this->getOption('order') ? $this->getOption('order') : $this->_getColName('left') |
769 |
); |
); |
770 |
if( DB::isError( $_res = $this->dbh->getAll($query) ) ) |
if (DB::isError($_res = $this->dbh->getAll($query))) { |
|
{ |
|
771 |
return $this->_throwError( $_res->getMessage() , __LINE__ ); |
return $this->_throwError( $_res->getMessage() , __LINE__ ); |
772 |
} |
} |
773 |
$_res = $this->_prepareResults( $_res ); |
$_res = $this->_prepareResults( $_res ); |
774 |
|
|
775 |
// we use the id as the index, to make the use easier esp. for multiple return-values |
// we use the id as the index, to make the use easier esp. for multiple return-values |
776 |
$tempRes = array(); |
$tempRes = array(); |
777 |
foreach( $_res as $aRes ) |
foreach ($_res as $aRes) { |
|
{ |
|
778 |
$tempRes[$aRes[$this->_getColName('id')]] = $aRes; |
$tempRes[$aRes[$this->_getColName('id')]] = $aRes; |
779 |
} |
} |
780 |
$_res = $tempRes; |
$_res = $tempRes; |
781 |
|
|
782 |
// |
// |
783 |
if( $levels>1 ) |
if ($levels>1) { |
|
{ |
|
784 |
$ids = array(); |
$ids = array(); |
785 |
foreach( $_res as $aRes ) |
foreach( $_res as $aRes ) |
786 |
$ids[] = $aRes[$this->_getColName('id')]; |
$ids[] = $aRes[$this->_getColName('id')]; |
788 |
$res = array_merge($res,$_res); |
$res = array_merge($res,$_res); |
789 |
|
|
790 |
// quit the for-loop if there are no children in the current level |
// quit the for-loop if there are no children in the current level |
791 |
if( !sizeof($ids) ) |
if (!sizeof($ids)) { |
792 |
break; |
break; |
793 |
|
} |
794 |
} |
} |
795 |
return $res; |
return $res; |
796 |
} |
} |
874 |
{ |
{ |
875 |
// check simply if the left and right of the child are within the |
// check simply if the left and right of the child are within the |
876 |
// left and right of the parent, if so it definitly is a child :-) |
// left and right of the parent, if so it definitly is a child :-) |
877 |
$parent = $this->getElement( $id ); |
$parent = $this->getElement($id); |
878 |
$child = $this->getElement( $childId ); |
$child = $this->getElement($childId); |
879 |
|
|
880 |
if( $parent['left'] < $child['left'] && |
if( $parent['left'] < $child['left'] && |
881 |
$parent['right'] > $child['right'] ) |
$parent['right'] > $child['right'] ) |
886 |
return false; |
return false; |
887 |
} // end of function |
} // end of function |
888 |
|
|
889 |
|
/** |
890 |
|
* return the maximum depth of the tree |
891 |
|
* |
892 |
|
* @version 2003/02/25 |
893 |
|
* @access public |
894 |
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
895 |
|
* @return int the depth of the tree |
896 |
|
*/ |
897 |
|
function getDepth() |
898 |
|
{ |
899 |
|
// FIXXXME TODO!!! |
900 |
|
return $this->_throwError( 'not implemented yet' , __LINE__ ); |
901 |
|
} |
902 |
|
|
903 |
|
/** |
904 |
|
* Tells if the node with the given ID has children. |
905 |
|
* |
906 |
|
* @version 2003/03/04 |
907 |
|
* @access public |
908 |
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
909 |
|
* @param integer the ID of a node |
910 |
|
* @return boolean if the node with the given id has children |
911 |
|
*/ |
912 |
|
function hasChildren($id) |
913 |
|
{ |
914 |
|
$element = $this->getElement($id); |
915 |
|
return $element['right']-$element['left']>1; // if the diff between left and right>1 then there are children |
916 |
|
} |
917 |
|
|
918 |
|
|
919 |
// |
// |