| // +----------------------------------------------------------------------+ // // $Id: Common.php,v 1.21 2003/03/04 18:59:21 cain Exp $ require_once('Tree/OptionsDB.php'); define("TREE_ERROR", -1); define("TREE_ERROR_INVALID_PARENT", -2); /** * common tree class, implements common functionality * * this class extends Tree_OptionsDB so every class that extends this oe can * connect to a db and set options * * @access public * @author Wolfram Kriesing * @version 2001/06/27 * @package Tree */ class Tree_Common extends Tree_OptionsDB { /** * put proper value-keys are given in each class, depending on the implementation * only some options are needed or allowed, see the classes which extend this one * * @access public * @var array saves the options passed to the constructor */ var $options = array(); /** * * * @version 2002/01/18 * @access public * @author Wolfram Kriesing */ function getChildId( $id ) { $child = $this->getChild( $id ); return $child['id']; } /** * get the ids of the children of the given element * * @version 2002/02/06 * @access public * @author Wolfram Kriesing * @param integer $id ID of the element that the children shall be retreived for * @param integer how many levels deep into the tree * @return mixed an array of all the ids of the children of the element with id=$id, * or false if there are no children */ function getChildrenIds($id,$levels=1) { if (!($children = $this->getChildren($id,$levels))) { // returns false if no children exist return array(); // return an empty array, if you want to know if there are children, use hasChildren } if ($children && sizeof($children)) { foreach ($children as $aChild) { $childrenIds[] = $aChild['id']; } } return $childrenIds; } /** * gets all the children and grand children etc. * * @version 2002/09/30 * @access public * @author Wolfram Kriesing * @param integer $id ID of the element that the children shall be retreived for * @return mixed an array of all the children of the element with id=$id, * or false if there are no children */ // FIXXXME remove this method and replace it by getChildren($id,0) function getAllChildren($id) { $retChildren = false; if ($children = $this->hasChildren($id)) { $retChildren = $this->_getAllChildren( $id ); } return $retChildren; } /** * this method gets all the children recursively * * @see getAllChildren() * @version 2002/09/30 * @access public * @author Wolfram Kriesing * @param integer $id ID of the element that the children shall be retreived for * @return mixed an array of all the ids of the children of the element with id=$id, * or false if there are no children */ function &_getAllChildren($id) { $retChildren = array(); if ($children = $this->getChildren($id)) { foreach ($children as $key=>$aChild) { $retChildren[] = &$children[$key]; $retChildren = array_merge($retChildren,$this->_getAllChildren( $aChild['id'] )); } } return $retChildren; } /** * gets all the children-ids and grand children-ids * * @version 2002/09/30 * @access public * @author Wolfram Kriesing * @param integer $id ID of the element that the children shall be retreived for * @return mixed an array of all the ids of the children of the element with id=$id, * or false if there are no children */ function getAllChildrenIds( $id ) { $childrenIds = array(); if( $allChildren = $this->getAllChildren($id) ) { $childrenIds = array(); foreach( $allChildren as $aNode ) $childrenIds[] = $aNode['id']; } return $childrenIds; } /** * get the id of the parent for the given element * * @version 2002/01/18 * @access public * @param integer $id the id of the element for which the parentId shall be retreived * @author Wolfram Kriesing */ function getParentId( $id ) { $parent = $this->getParent( $id ); return $parent['id']; } /** * this gets all the preceeding nodes, the parent and it's parent and so on * * @version 2002/08/19 * @access public * @author Wolfram Kriesing * @param integer $id the id of the element for which the parentId shall be retreived * @return array of the parent nodes including the node with id $id */ function getParents( $id ) { $path = $this->getPath($id); $parents = array(); if( sizeof($path) ) foreach( $path as $aNode ) $parents[] = $aNode; return $parents; } /** * get the ids of the parents and all it's parents and so on * it simply returns the ids of the elements returned by getParents() * @see getParents() * @version 2002/08/19 * @access public * @author Wolfram Kriesing * @param integer $id the id of the element for which the parentId shall be retreived * @return array of the ids */ function getParentsIds( $id ) { $parents = $this->getParents($id); $parentsIds = array(); if( sizeof($parents) ) foreach( $parents as $aNode ) $parentsIds[] = $aNode['id']; return $parentsIds; } /** * * * @version 2002/01/18 * @access public * @author Wolfram Kriesing */ function getNextId( $id ) { $next = $this->getNext( $id ); return $next['id']; } /** * * * @version 2002/01/18 * @access public * @author Wolfram Kriesing */ function getPreviousId( $id ) { $previous = $this->getPrevious( $id ); return $previous['id']; } /** * * * @version 2002/01/18 * @access public * @author Wolfram Kriesing */ function getLeftId( $id ) { $left = $this->getLeft( $id ); return $left['id']; } /** * * * @version 2002/01/18 * @access public * @author Wolfram Kriesing */ function getRightId( $id ) { $right = $this->getRight( $id ); return $right['id']; } /** * * * @version 2002/01/18 * @access public * @author Wolfram Kriesing */ function getFirstRootId() { $firstRoot = $this->getFirstRoot(); return $firstRoot['id']; } /** * * * @version 2002/04/16 * @access public * @author Wolfram Kriesing */ function getRootId() { $firstRoot = $this->getRoot(); return $firstRoot['id']; } /** * returns the path as a string * * @access public * @version 2002/03/28 * @access public * @author Wolfram Kriesing * @param mixed $id the id of the node to get the path for * @param integer If offset is positive, the sequence will * start at that offset in the array . If * offset is negative, the sequence will start that far from the end of the array . * @param integer If length is given and is positive, then * the sequence will have that many elements in it. If * length is given and is negative then the * sequence will stop that many elements from the end of the * array. If it is omitted, then the sequence will have everything * from offset up until the end of the array. * @return array this array contains all elements from the root to the element given by the id * */ function getPathAsString( $id , $seperator='/' , $offset=0 , $length=0 ) { $path = $this->getPath($id); foreach ($path as $aNode) { $pathArray[] = $aNode['name']; } if ($offset) { if ($length) { $pathArray = array_slice($pathArray,$offset,$length); } else { $pathArray = array_slice($pathArray,$offset); } } $pathString = ''; if( sizeof($pathArray) ) $pathString = implode($seperator,$pathArray); return $pathString; } // end of function // // abstract methods, those should be overwritten by the implementing class // /** * gets the path to the element given by its id * * @abstract * @version 2001/10/10 * @access public * @author Wolfram Kriesing * @param mixed $id the id of the node to get the path for * @return array this array contains all elements from the root to the element given by the id * */ function getPath( $id ) { return $this->_throwError( 'not implemented, at least not overwritten the abstract declaration' , __LINE__ ); } // end of function /** * get the level, which is how far below the root the element with the given id is * * @abstract * @version 2001/11/25 * @access public * @author Wolfram Kriesing * @param mixed $id the id of the node to get the level for * */ function getLevel( $id ) { return $this->_throwError( 'not implemented, at least not overwritten the abstract declaration' , __LINE__ ); } // end of function /** * returns if $childId is a child of $id * * @abstract * @version 2002/04/29 * @access public * @author Wolfram Kriesing * @param int id of the element * @param int id of the element to check if it is a child * @param boolean if this is true the entire tree below is checked * @return boolean true if it is a child */ function isChildOf( $id , $childId , $checkAll=true ) { return $this->_throwError( 'not implemented, at least not overwritten the abstract declaration' , __LINE__ ); } // end of function /** * return the maximum depth of the tree * * @version 2003/02/25 * @access public * @author Wolfram Kriesing * @return int the depth of the tree */ function getDepth() { return $this->_treeDepth; } // end of function // // PRIVATE METHODS // /** * prepare multiple results * * @see _prepareResult() * @access private * @version 2002/03/03 * @author Wolfram Kriesing * @param * @return */ function _prepareResults( $results ) { $newResults = array(); foreach( $results as $key=>$aResult ) $newResults[$key] = $this->_prepareResult($aResult); return $newResults; } /** * map back the index names to get what is expected * * @access private * @version 2002/03/03 * @author Wolfram Kriesing * @param * @return */ function _prepareResult( $result ) { $map = $this->getOption('columnNameMaps'); if( $map ) foreach( $map as $key=>$columnName ) { $result[$key] = $result[$columnName]; unset($result[$columnName]); } return $result; } /** * this method retreives the real column name, as used in the DB * since the internal names are fixed, to be portable between different * DB-column namings, we map the internal name to the real column name here * * @access private * @version 2002/03/02 * @author Wolfram Kriesing * @param * @return */ function _getColName( $internalName ) { if( $map = $this->getOption( 'columnNameMaps' ) ) { if( isset($map[$internalName]) ) return $map[$internalName]; } return $internalName; } /** * * * @access private * @version 2002/03/02 * @author Wolfram Kriesing * @param * @return */ function _throwError( $msg , $line , $mode=null ) { if( $mode===null && $this->debug>0 ) $mode = PEAR_ERROR_PRINT; return new Tree_Error( $msg , $line , __FILE__ , $mode , $this->dbh->last_query ); } } ?>