| 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 |
// |
// |