Created
January 4, 2012 22:23
-
-
Save CloCkWeRX/1562520 to your computer and use it in GitHub Desktop.
Tree - 0_3_0 vs trunk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: Tree/Error.php | |
=================================================================== | |
--- Tree/Error.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Error.php (.../trunk) (revision 321102) | |
@@ -1,86 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: Wolfram Kriesing <[email protected]> | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
-require_once 'PEAR.php'; | |
- | |
-/** | |
- * Errors constants definitions | |
- */ | |
-define('TREE_ERROR_NOT_IMPLEMENTED', -1); | |
-define('TREE_ERROR_ELEMENT_NOT_FOUND', -2); | |
-define('TREE_ERROR_INVALID_NODE_NAME', -3); | |
-define('TREE_ERROR_MOVE_TO_CHILDREN', -4); | |
-define('TREE_ERROR_PARENT_ID_MISSED', -5); | |
-define('TREE_ERROR_INVALID_PARENT', -6); | |
-define('TREE_ERROR_EMPTY_PATH', -7); | |
-define('TREE_ERROR_INVALID_PATH', -8); | |
-define('TREE_ERROR_DB_ERROR', -9); | |
-define('TREE_ERROR_PATH_SEPARATOR_EMPTY',-10); | |
-define('TREE_ERROR_CANNOT_CREATE_FOLDER',-11); | |
-define('TREE_ERROR_UNKNOW_ERROR', -99); | |
- | |
-/** | |
- * | |
- * | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @package Tree | |
- */ | |
-class Tree_Error extends PEAR_Error | |
-{ | |
- /** | |
- * @var string prefix for error messages. | |
- */ | |
- var $error_message_prefix = "Tree Error: "; | |
- | |
- // {{{ Tree_Error() | |
- | |
- /** | |
- * @access public | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function Tree_Error($msg, $line, $file, | |
- $mode = null, $userinfo = 'no userinfo') | |
- { | |
- $this->PEAR_Error(sprintf("%s <br/>in %s [%d].", $msg, $file, $line), | |
- null , $mode , null, $userinfo ); | |
- } | |
- | |
- // }}} | |
- // {{{ getMessage() | |
- | |
- function getMessage($id) | |
- { | |
- $messages = array( | |
- TREE_ERROR_NOT_IMPLEMENTED => '', | |
- TREE_ERROR_INVALID_PATH => '', | |
- TREE_ERROR_DB_ERROR => '', | |
- TREE_ERROR_PARENT_ID_MISSED => '', | |
- TREE_ERROR_MOVE_TO_CHILDREN => '', | |
- TREE_ERROR_ELEMENT_NOT_FOUND => '', | |
- TREE_ERROR_PATH_SEPARATOR_EMPTY => '', | |
- TREE_ERROR_INVALID_NODE_NAME => '', | |
- TREE_ERROR_UNKNOW_ERROR => '' | |
- ); | |
- return isset($messages[$id])?$messages[$id]: | |
- $messages[TREE_ERROR_UNKNOW_ERROR]; | |
- } | |
- | |
- // }}} | |
-} | |
\ No newline at end of file | |
Index: Tree/OptionsMDB.php | |
=================================================================== | |
--- Tree/OptionsMDB.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/OptionsMDB.php (.../trunk) (revision 321102) | |
@@ -1,113 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// i think this class should go somewhere in a common PEAR-place, | |
-// because a lot of classes use options, at least PEAR::DB does | |
-// but since it is not very fancy to crowd the PEAR-namespace | |
-// too much i dont know where to put it yet :-( | |
- | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: Wolfram Kriesing <[email protected]> | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/Common.php'; | |
- | |
-/** | |
-* this class additionally retreives a DB connection and saves it | |
-* in the property "dbh" | |
-* | |
-* @package Tree | |
-* @access public | |
-* @author Wolfram Kriesing <[email protected]> | |
-* | |
-*/ | |
-class Tree_OptionsMDB extends Tree_Common | |
-{ | |
- /** | |
- * @var object | |
- */ | |
- var $dbh; | |
- | |
- // {{{ Tree_OptionsMDB() | |
- | |
- /** | |
- * this constructor sets the options, since i normally need this and | |
- * in case the constructor doesnt need to do anymore i already have | |
- * it done :-) | |
- * | |
- * @version 02/01/08 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param boolean true if loggedIn | |
- */ | |
- function Tree_OptionsMDB($dsn, $options=array()) | |
- { | |
- $res = $this->_connectDB($dsn); | |
- if (PEAR::isError($res)) { | |
- return $res; | |
- } | |
- | |
- $this->dbh->setFetchmode(MDB_FETCHMODE_ASSOC); | |
- // do options afterwards since it overrules | |
- $this->Tree_Options($options); | |
- } | |
- | |
- // }}} | |
- // {{{ _connectDB() | |
- | |
- /** | |
- * Connect to database by using the given DSN string | |
- * | |
- * @author copied from PEAR::Auth, Martin Jansen, slightly modified | |
- * @access private | |
- * @param string DSN string | |
- * @return mixed Object on error, otherwise bool | |
- */ | |
- function _connectDB($dsn) | |
- { | |
- // only include the db if one really wants to connect | |
- require_once 'MDB.php'; | |
- | |
- if (is_string($dsn) || is_array($dsn)) { | |
- $this->dbh = MDB::Connect($dsn); | |
- } else { | |
- if (strtolower(get_parent_class($dsn)) == 'mdb_common') { | |
- $this->dbh = $dsn; | |
- } else { | |
- if (is_object($dsn) && MDB::isError($dsn)) { | |
- return new MDB_Error($dsn->code, PEAR_ERROR_DIE); | |
- } | |
- | |
- return new PEAR_Error( | |
- 'The given dsn was not valid in file '. | |
- __FILE__ . ' at line ' . __LINE__, | |
- 41, | |
- PEAR_ERROR_RETURN, | |
- null, | |
- null | |
- ); | |
- } | |
- } | |
- | |
- if (MDB::isError($this->dbh)) { | |
- return new MDB_Error($this->dbh->code, PEAR_ERROR_DIE); | |
- } | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
-} | |
\ No newline at end of file | |
Index: Tree/OptionsMDB2.php | |
=================================================================== | |
--- Tree/OptionsMDB2.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/OptionsMDB2.php (.../trunk) (revision 321102) | |
@@ -1,114 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// i think this class should go somewhere in a common PEAR-place, | |
-// because a lot of classes use options, at least PEAR::DB does | |
-// but since it is not very fancy to crowd the PEAR-namespace | |
-// too much i dont know where to put it yet :-( | |
- | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: Wolfram Kriesing <[email protected]> | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/Common.php'; | |
- | |
-/** | |
-* this class additionally retreives a DB connection and saves it | |
-* in the property "dbh" | |
-* | |
-* @package Tree | |
-* @access public | |
-* @author Wolfram Kriesing <[email protected]> | |
-* | |
-*/ | |
-class Tree_OptionsMDB2 extends Tree_Common | |
-{ | |
- /** | |
- * @var object | |
- */ | |
- var $dbh; | |
- | |
- // {{{ Tree_OptionsMDB2() | |
- | |
- /** | |
- * this constructor sets the options, since i normally need this and | |
- * in case the constructor doesnt need to do anymore i already have | |
- * it done :-) | |
- * | |
- * @version 02/01/08 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param boolean true if loggedIn | |
- */ | |
- function Tree_OptionsMDB2($dsn, $options = array()) | |
- { | |
- $res = $this->_connectDB($dsn); | |
- if (PEAR::isError($res)) { | |
- return $res; | |
- } | |
- | |
- $this->dbh->setFetchmode(MDB2_FETCHMODE_ASSOC); | |
- // do options afterwards since it overrules | |
- $this->Tree_Options($options); | |
- } | |
- | |
- // }}} | |
- // {{{ _connectDB() | |
- | |
- /** | |
- * Connect to database by using the given DSN string | |
- * | |
- * @author copied from PEAR::Auth, Martin Jansen, slightly modified | |
- * @access private | |
- * @param string DSN string | |
- * @return mixed Object on error, otherwise bool | |
- */ | |
- function _connectDB($dsn) | |
- { | |
- // only include the db if one really wants to connect | |
- require_once 'MDB2.php'; | |
- | |
- if (is_string($dsn) || is_array($dsn)) { | |
- $this->dbh = MDB2::Connect($dsn); | |
- } else { | |
- if (MDB2::isConnection($dsn)) { | |
- $this->dbh = $dsn; | |
- } else { | |
- if (is_object($dsn) && MDB2::isError($dsn)) { | |
- return new MDB2_Error($dsn->code, PEAR_ERROR_DIE); | |
- } | |
- | |
- return new PEAR_Error( | |
- 'The given dsn was not valid in file '. | |
- __FILE__ . ' at line ' . __LINE__, | |
- 41, | |
- PEAR_ERROR_RETURN, | |
- null, | |
- null | |
- ); | |
- | |
- } | |
- } | |
- | |
- if (MDB2::isError($this->dbh)) { | |
- return new MDB2_Error($this->dbh->code, PEAR_ERROR_DIE); | |
- } | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
-} | |
\ No newline at end of file | |
Index: Tree/OptionsDB.php | |
=================================================================== | |
--- Tree/OptionsDB.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/OptionsDB.php (.../trunk) (revision 321102) | |
@@ -1,122 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
- | |
-// i think this class should go somewhere in a common PEAR-place, | |
-// but since it is not very fancy to crowd the PEAR-namespace too much | |
-// i dont know where to put it yet :-( | |
- | |
-// | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: Wolfram Kriesing <[email protected]> | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/Common.php'; | |
- | |
-/** | |
- * this class additionally retreives a DB connection and saves it | |
- * in the property "dbh" | |
- * | |
- * @package Tree | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * | |
- */ | |
-class Tree_OptionsDB extends Tree_Common | |
-{ | |
- /** | |
- * @var object | |
- */ | |
- var $dbh; | |
- | |
- | |
- // {{{ Tree_OptionsDB() | |
- | |
- /** | |
- * this constructor sets the options, since i normally need this and | |
- * in case the constructor doesnt need to do anymore i already have | |
- * it done :-) | |
- * | |
- * @version 02/01/08 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param boolean true if loggedIn | |
- */ | |
- function Tree_OptionsDB($dsn , $options = array()) | |
- { | |
- $res = $this->_connectDB($dsn); | |
- if (PEAR::isError($res)) { | |
- return $res; | |
- } | |
- | |
- $this->dbh->setFetchmode(DB_FETCHMODE_ASSOC); | |
- // do options afterwards since it overrules | |
- $this->Tree_Options($options); | |
- } | |
- | |
- // }}} | |
- // {{{ _connectDB() | |
- | |
- /** | |
- * Connect to database by using the given DSN string | |
- * | |
- * @author copied from PEAR::Auth, Martin Jansen, slightly modified | |
- * @access private | |
- * @param string DSN string | |
- * @return mixed Object on error, otherwise bool | |
- */ | |
- function _connectDB($dsn) | |
- { | |
- // only include the db if one really wants to connect | |
- require_once 'DB.php'; | |
- | |
- if (is_string($dsn) || is_array($dsn)) { | |
- // put the dsn parameters in an array | |
- // DB would be confused with an additional URL-queries, | |
- //like ?table=... so we do it before connecting to the DB | |
- if (is_string($dsn)) { | |
- $dsn = DB::parseDSN($dsn); | |
- } | |
- $this->dbh = DB::Connect($dsn); | |
- } else { | |
- if (strtolower(get_parent_class($dsn)) == 'db_common') { | |
- $this->dbh = $dsn; | |
- } else { | |
- if (is_object($dsn) && DB::isError($dsn)) { | |
- return new DB_Error($dsn->code, PEAR_ERROR_DIE); | |
- } | |
- | |
- return new PEAR_Error( | |
- 'The given dsn was not valid in file '. | |
- __FILE__ . " at line " . __LINE__, | |
- 41, | |
- PEAR_ERROR_RETURN, | |
- null, | |
- null | |
- ); | |
- | |
- } | |
- } | |
- | |
- if (DB::isError($this->dbh)) { | |
- return new DB_Error($this->dbh->code, PEAR_ERROR_DIE); | |
- } | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
-} | |
\ No newline at end of file | |
Index: Tree/Common.php | |
=================================================================== | |
--- Tree/Common.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Common.php (.../trunk) (revision 321102) | |
@@ -1,845 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: Wolfram Kriesing <[email protected]> | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/Tree.php'; | |
-require_once 'Tree/Error.php'; | |
- | |
-/** | |
- * common tree class, implements common functionality | |
- * | |
- * | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @version 2001/06/27 | |
- * @package Tree | |
- */ | |
-class Tree_Common | |
-{ | |
- /** | |
- * @var array you need to overwrite this array and give the keys/ | |
- * that are allowed | |
- */ | |
- var $_forceSetOption = false; | |
- | |
- /** | |
- * 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(); | |
- | |
- | |
- // {{{ getChildId() | |
- | |
- /** | |
- * @version 2002/01/18 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function getChildId($id) | |
- { | |
- $child = $this->getChild($id); | |
- return $child['id']; | |
- } | |
- | |
- // }}} | |
- // {{{ getChildrenIds() | |
- | |
- /** | |
- * get the ids of the children of the given element | |
- * | |
- * @version 2002/02/06 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer 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) | |
- { | |
- // returns false if no children exist | |
- if (!($children = $this->getChildren($id, $levels))) { | |
- 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; | |
- } | |
- | |
- // }}} | |
- // {{{ getAllChildren() | |
- | |
- /** | |
- * gets all the children and grand children etc. | |
- * | |
- * @version 2002/09/30 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer 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; | |
- } | |
- | |
- // }}} | |
- // {{{ _getAllChildren() | |
- | |
- /** | |
- * this method gets all the children recursively | |
- * | |
- * @see getAllChildren() | |
- * @version 2002/09/30 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer 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; | |
- } | |
- | |
- // }}} | |
- // {{{ getAllChildrenIds() | |
- | |
- /** | |
- * gets all the children-ids and grand children-ids | |
- * | |
- * @version 2002/09/30 | |
- * @access public | |
- * @author Kriesing <[email protected]> | |
- * @param integer 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; | |
- } | |
- | |
- // }}} | |
- // {{{ getParentId() | |
- | |
- /** | |
- * get the id of the parent for the given element | |
- * | |
- * @version 2002/01/18 | |
- * @access public | |
- * @param integer the id of the element for which the parentId | |
- * shall be retreived | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function getParentId($id) | |
- { | |
- $parent = $this->getParent($id); | |
- return $parent['id']; | |
- } | |
- | |
- // }}} | |
- // {{{ getParents() | |
- | |
- /** | |
- * this gets all the preceeding nodes, the parent and it's parent and so on | |
- * | |
- * @version 2002/08/19 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer 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; | |
- } | |
- | |
- // }}} | |
- // {{{ getParentsIds() | |
- | |
- /** | |
- * 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 <[email protected]> | |
- * @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; | |
- } | |
- | |
- // }}} | |
- // {{{ getNextId() | |
- | |
- /** | |
- * @version 2002/01/18 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function getNextId($id) | |
- { | |
- $next = $this->getNext($id); | |
- return $next['id']; | |
- } | |
- | |
- // }}} | |
- // {{{ getPreviousId() | |
- | |
- /** | |
- * @version 2002/01/18 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function getPreviousId($id) | |
- { | |
- $previous = $this->getPrevious($id); | |
- return $previous['id']; | |
- } | |
- | |
- // }}} | |
- // {{{ getLeftId() | |
- | |
- /** | |
- * @version 2002/01/18 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function getLeftId($id) | |
- { | |
- $left = $this->getLeft($id); | |
- return $left['id']; | |
- } | |
- | |
- // }}} | |
- // {{{ getRightId() | |
- | |
- /** | |
- * @version 2002/01/18 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function getRightId($id) | |
- { | |
- $right = $this->getRight($id); | |
- return $right['id']; | |
- } | |
- | |
- // }}} | |
- // {{{ getFirstRootId() | |
- | |
- /** | |
- * @version 2002/04/16 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function getFirstRootId() | |
- { | |
- $firstRoot = $this->getFirstRoot(); | |
- return $firstRoot['id']; | |
- } | |
- | |
- // }}} | |
- // {{{ getRootId() | |
- | |
- /** | |
- * @version 2002/04/16 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function getRootId() | |
- { | |
- $firstRoot = $this->getRoot(); | |
- return $firstRoot['id']; | |
- } | |
- | |
- // }}} | |
- // {{{ getPathAsString() | |
- | |
- /** | |
- * returns the path as a string | |
- * | |
- * @access public | |
- * @version 2002/03/28 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @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. | |
- * @param string you can tell the key the path shall be used to be | |
- * constructed with i.e. giving 'name' (=default) would | |
- * use the value of the $element['name'] for the node-name | |
- * (thanks to Michael Johnson). | |
- * | |
- * @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, $key = 'name') | |
- { | |
- $path = $this->getPath($id); | |
- foreach ($path as $aNode) { | |
- $pathArray[] = $aNode[$key]; | |
- } | |
- | |
- 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; | |
- } | |
- | |
- // }}} | |
- | |
- | |
- // | |
- // abstract methods, those should be overwritten by the implementing class | |
- // | |
- | |
- // {{{ getPath() | |
- | |
- /** | |
- * gets the path to the element given by its id | |
- * | |
- * @abstract | |
- * @version 2001/10/10 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @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->_raiseError(TREE_ERROR_NOT_IMPLEMENTED, | |
- __FUNCTION__, __LINE__); | |
- } | |
- | |
- // }}} | |
- // {{{ _preparePath() | |
- | |
- /** | |
- * gets the path to the element given by its id | |
- * | |
- * @version 2003/05/11 | |
- * @access private | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param mixed $id the id of the node to get the path for | |
- * @return array this array contains the path elements and the sublevels | |
- * to substract if no $cwd has been given. | |
- */ | |
- function _preparePath($path, $cwd = '/', $separator = '/'){ | |
- $elems = explode($separator, $path); | |
- $cntElems = sizeof($elems); | |
- // beginning with a slash | |
- if (empty($elems[0])) { | |
- $beginSlash = true; | |
- array_shift($elems); | |
- $cntElems--; | |
- } | |
- // ending with a slash | |
- if (empty($elems[$cntElems-1])) { | |
- $endSlash = true; | |
- array_pop($elems); | |
- $cntElems--; | |
- } | |
- // Get the real path, and the levels | |
- // to substract if required | |
- $down = 0; | |
- while ($elems[0] == '..') { | |
- array_shift($elems); | |
- $down++; | |
- } | |
- if ($down >= 0 && $cwd == '/') { | |
- $down = 0; | |
- $_elems = array(); | |
- $sublevel = 0; | |
- $_elems = array(); | |
- } else { | |
- list($_elems, $sublevel) = $this->_preparePath($cwd); | |
- } | |
- $i = 0; | |
- foreach($elems as $val){ | |
- if (trim($val) == '') { | |
- return $this->_raiseError(TREE_ERROR_INVALID_PATH, | |
- __FUNCTION__, __LINE__); | |
- } | |
- if ($val == '..') { | |
- if ($i == 0) { | |
- $down++; | |
- } else { | |
- $i--; | |
- } | |
- } else { | |
- $_elems[$i++] = $val; | |
- } | |
- } | |
- if (sizeof($_elems) < 1){ | |
- return $this->_raiseError(TREE_ERROR_EMPTY_PATH, | |
- __FUNCTION__, __LINE__); | |
- } | |
- return array($_elems, $sublevel); | |
- } | |
- | |
- // }}} | |
- // {{{ getLevel() | |
- | |
- /** | |
- * 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 <[email protected]> | |
- * @param mixed $id the id of the node to get the level for | |
- * | |
- */ | |
- function getLevel($id) | |
- { | |
- return $this->_raiseError(TREE_ERROR_NOT_IMPLEMENTED, | |
- __FUNCTION__, __LINE__); | |
- } | |
- | |
- // }}} | |
- // {{{ isChildOf() | |
- | |
- /** | |
- * returns if $childId is a child of $id | |
- * | |
- * @abstract | |
- * @version 2002/04/29 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @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->_raiseError(TREE_ERROR_NOT_IMPLEMENTED, | |
- __FUNCTION__, __LINE__); | |
- } | |
- | |
- // }}} | |
- // {{{ getIdByPath() | |
- | |
- /** | |
- * | |
- * | |
- */ | |
- function getIdByPath($path, $startId = 0, | |
- $nodeName = 'name', $seperator = '/') | |
- { | |
- return $this->_raiseError(TREE_ERROR_NOT_IMPLEMENTED, | |
- __FUNCTION__, __LINE__); | |
- } | |
- | |
- // }}} | |
- // {{{ getDepth() | |
- | |
- /** | |
- * return the maximum depth of the tree | |
- * | |
- * @version 2003/02/25 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @return int the depth of the tree | |
- */ | |
- function getDepth() | |
- { | |
- return $this->_treeDepth; | |
- } | |
- | |
- // }}} | |
- | |
- // | |
- // PRIVATE METHODS | |
- // | |
- | |
- // {{{ _prepareResults() | |
- | |
- /** | |
- * prepare multiple results | |
- * | |
- * @see _prepareResult() | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array the data to prepare | |
- * @return array prepared results | |
- */ | |
- function &_prepareResults($results) | |
- { | |
- $newResults = array(); | |
- foreach ($results as $key => $aResult) { | |
- $newResults[$key] = $this->_prepareResult($aResult); | |
- } | |
- return $newResults; | |
- } | |
- | |
- // }}} | |
- // {{{ _prepareResult() | |
- | |
- /** | |
- * map back the index names to get what is expected | |
- * | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array a result | |
- * @return array the prepared result | |
- */ | |
- function _prepareResult($result) | |
- { | |
- $map = $this->getOption('columnNameMaps'); | |
- if ($map) { | |
- foreach ($map as $key => $columnName) { | |
- if (isset($result[$columnName])) { | |
- $temp = $result[$columnName]; // remember the value from the old name | |
- unset($result[$columnName]); // remove the old one | |
- $result[$key] = $temp; // save it in the mapped col-name | |
- } | |
- } | |
- } | |
- return $result; | |
- } | |
- | |
- // }}} | |
- // {{{ _getColName() | |
- | |
- /** | |
- * this method retrieves 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 <[email protected]> | |
- * @param string the internal name used | |
- * @return string the real name of the column | |
- */ | |
- function _getColName($internalName) | |
- { | |
- if ($map = $this->getOption('columnNameMaps')) { | |
- if (isset($map[$internalName])) { | |
- return $map[$internalName]; | |
- } | |
- } | |
- return $internalName; | |
- } | |
- | |
- // }}} | |
- // {{{ _raiseError() | |
- | |
- /** | |
- * | |
- * | |
- * @access private | |
- * @version 2002/03/02 | |
- * @author Pierre-Alain Joye <[email protected]> | |
- * @param string the error message | |
- * @param int the line in which the error occured | |
- * @param mixed the error mode | |
- * @return object a Tree_Error | |
- */ | |
- function _raiseError($errorCode, $msg = '', $line = 0) | |
- { | |
- include_once 'Tree/Error.php'; | |
- return new Tree_Error( | |
- $msg, $line, __FILE__, $mode, $this->dbh->last_query); | |
- } | |
- | |
- // }}} | |
- // {{{ _throwError() | |
- | |
- /** | |
- * | |
- * | |
- * @access private | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param string the error message | |
- * @param int the line in which the error occured | |
- * @param mixed the error mode | |
- * @return object a Tree_Error | |
- */ | |
- function _throwError($msg, $line, $mode = null) | |
- { | |
- include_once 'Tree/Error.php'; | |
- if ($mode === null && $this->debug > 0) { | |
- $mode = PEAR_ERROR_PRINT; | |
- } | |
- return new Tree_Error( | |
- $msg, $line, __FILE__, $mode, $this->dbh->last_query); | |
- } | |
- | |
- // }}} | |
- | |
- | |
- /*******************************************************************************/ | |
- /************************ METHODS FROM Tree_Memory *****************************/ | |
- /*******************************************************************************/ | |
- | |
- /** | |
- * returns if the given element has any children | |
- * | |
- * @version 2001/12/17 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer $id the id of the node to check for children | |
- * @return boolean true if the node has children | |
- */ | |
- function hasChildren($id = 0) | |
- { | |
- if (isset($this->data[$id]['children']) && | |
- sizeof($this->data[$id]['children']) > 0) { | |
- return true; | |
- } | |
- return false; | |
- } | |
- | |
- | |
- | |
- | |
- | |
- /*******************************************************************************/ | |
- /************************ METHODS FROM Tree_Options ****************************/ | |
- /*******************************************************************************/ | |
- | |
- | |
- | |
- // {{{ Tree_Options() | |
- | |
- /** | |
- * this constructor sets the options, since i normally need this and | |
- * in case the constructor doesnt need to do anymore i already have | |
- * it done :-) | |
- * | |
- * @version 02/01/08 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array the key-value pairs of the options that shall be set | |
- * @param boolean if set to true options are also set | |
- * even if no key(s) was/were found in the options property | |
- */ | |
- function Tree_Options($options=array(), $force=false) | |
- { | |
- $this->_forceSetOption = $force; | |
- if (is_array($options) && sizeof($options)) { | |
- foreach ($options as $key=>$value) { | |
- $this->setOption($key, $value); | |
- } | |
- } | |
- } | |
- | |
- // }}} | |
- // {{{ setOption() | |
- | |
- /** | |
- * | |
- * @access public | |
- * @author Stig S. Baaken | |
- * @param string the option name | |
- * @param mixed the value for this option | |
- * @param boolean if set to true options are also set | |
- * even if no key(s) was/were found in the options property | |
- */ | |
- function setOption($option, $value, $force = false) | |
- { | |
- // if the value is an array extract the keys | |
- // and apply only each value that is set | |
- if (is_array($value)) { | |
- // so we dont override existing options inside an array | |
- // if an option is an array | |
- foreach ($value as $key=>$aValue) { | |
- $this->setOption(array($option,$key),$aValue); | |
- } | |
- return true; | |
- } | |
- | |
- if (is_array($option)) { | |
- $mainOption = $option[0]; | |
- $options = "['".implode("']['",$option)."']"; | |
- $evalCode = "\$this->options".$options." = \$value;"; | |
- } else { | |
- $evalCode = "\$this->options[\$option] = \$value;"; | |
- $mainOption = $option; | |
- } | |
- | |
- if ($this->_forceSetOption == true || | |
- $force == true || isset($this->options[$mainOption])) { | |
- eval($evalCode); | |
- return true; | |
- } | |
- return false; | |
- } | |
- | |
- // }}} | |
- // {{{ setOptions() | |
- | |
- /** | |
- * set a number of options which are simply given in an array | |
- * | |
- * @access public | |
- * @param array the values to set | |
- * @param boolean if set to true options are also set even if no key(s) | |
- * was/were found in the options property | |
- */ | |
- function setOptions($options, $force = false) | |
- { | |
- if (is_array($options) && sizeof($options)) { | |
- foreach ($options as $key => $value) { | |
- $this->setOption($key, $value, $force); | |
- } | |
- } | |
- } | |
- | |
- // }}} | |
- // {{{ getOption() | |
- | |
- /** | |
- * | |
- * @access public | |
- * @author copied from PEAR: DB/commmon.php | |
- * @param boolean true on success | |
- */ | |
- function getOption($option) | |
- { | |
- if (func_num_args() > 1 && | |
- is_array($this->options[$option])) { | |
- $args = func_get_args(); | |
- $evalCode = "\$ret = \$this->options['". | |
- implode("']['", $args) . "'];"; | |
- eval($evalCode); | |
- return $ret; | |
- } | |
- | |
- if (isset($this->options[$option])) { | |
- return $this->options[$option]; | |
- } | |
- return false; | |
- } | |
- | |
- // }}} | |
- // {{{ getOptions() | |
- | |
- /** | |
- * returns all the options | |
- * | |
- * @version 02/05/20 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @return string all options as an array | |
- */ | |
- function getOptions() | |
- { | |
- return $this->options; | |
- } | |
- | |
- // }}} | |
-} | |
- | |
-/* | |
- * Local Variables: | |
- * mode: php | |
- * tab-width: 4 | |
- * c-basic-offset: 4 | |
- * End: | |
- */ | |
\ No newline at end of file | |
Index: Tree/Dynamic/MDBnested.php | |
=================================================================== | |
--- Tree/Dynamic/MDBnested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Dynamic/MDBnested.php (.../trunk) (revision 321102) | |
@@ -1,1283 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/OptionsMDB.php'; | |
- | |
-/** | |
-* This class implements methods to work on a tree saved using the nested | |
-* tree model. | |
-* explaination: http://research.calacademy.org/taf/proceedings/ballew/index.htm | |
-* | |
-* @access public | |
-* @package Tree | |
-*/ | |
-class Tree_Dynamic_MDBnested extends Tree_OptionsMDB | |
-{ | |
- | |
- // {{{ properties | |
- var $debug = 0; | |
- | |
- var $options = array( | |
- // FIXXME to be implemented | |
- // add on for the where clause, this string is simply added | |
- // behind the WHERE in the select so you better make sure | |
- // its correct SQL :-), i.e. 'uid=3' | |
- // this is needed i.e. when you are saving many trees in one db-table | |
- 'whereAddOn'=>'', | |
- 'table' =>'', | |
- // since the internal names are fixed, to be portable between different | |
- // DB tables with different column namings, we map the internal name | |
- // to the real column name using this array here, if it stays empty | |
- // the internal names are used, which are: | |
- // id, left, right | |
- 'columnNameMaps'=>array( | |
- // since mysql at least doesnt support 'left' ... | |
- 'left' => 'l', | |
- // ...as a column name we set default to the first | |
- //letter only | |
- 'right' => 'r', | |
- // parent id | |
- 'parentId' => 'parent' | |
- ), | |
- // needed for sorting the tree, currently only used in Memory_DBnested | |
- 'order' => '' | |
- ); | |
- | |
- // }}} | |
- // {{{ __construct() | |
- | |
- // the defined methods here are proposals for the implementation, | |
- // they are named the same, as the methods in the "Memory" branch. | |
- // If possible it would be cool to keep the same naming. And | |
- // if the same parameters would be possible too then it would be | |
- // even better, so one could easily change from any kind | |
- // of tree-implementation to another, without changing the source | |
- // code, only the setupXXX would need to be changed | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @param string the DSN for the DB connection | |
- * @return void | |
- */ | |
- function __construct($dsn, $options = array()) | |
- { | |
- $this->Tree_Dynamic_MDBnested($dsn, $options); | |
- } | |
- | |
- // }}} | |
- // {{{ Tree_Dynamic_DBnested() | |
- | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param string the DSN for the DB connection | |
- * @return void | |
- */ | |
- function Tree_Dynamic_MDBnested($dsn, $options = array()) | |
- { | |
- parent::Tree_OptionsMDB($dsn, $options); // instanciate DB | |
- $this->table = $this->getOption('table'); | |
- } | |
- | |
- // }}} | |
- // {{{ add() | |
- | |
- /** | |
- * add a new element to the tree | |
- * there are three ways to use this method | |
- * Method 1: | |
- * Give only the $parentId and the $newValues will be inserted | |
- * as the first child of this parent | |
- * <code> | |
- * // insert a new element under the parent with the ID=7 | |
- * $tree->add(array('name'=>'new element name'), 7); | |
- * </code> | |
- * | |
- * Method 2: | |
- * Give the $prevId ($parentId will be dismissed) and the new element | |
- * will be inserted in the tree after the element with the ID=$prevId | |
- * the parentId is not necessary because the prevId defines exactly where | |
- * the new element has to be place in the tree, and the parent is | |
- * the same as for the element with the ID=$prevId | |
- * <code> | |
- * // insert a new element after the element with the ID=5 | |
- * $tree->add(array('name'=>'new'), 0, 5); | |
- * </code> | |
- * | |
- * Method 3: | |
- * neither $parentId nor prevId is given, then the root element will be | |
- * inserted. This requires that programmer is responsible to confirm this. | |
- * This method does not yet check if there is already a root element saved! | |
- * | |
- * @access public | |
- * @param array $newValues this array contains the values that shall | |
- * be inserted in the db-table | |
- * @param integer $parentId the id of the element which shall be | |
- * the parent of the new element | |
- * @param integer $prevId the id of the element which shall preceed | |
- * the one to be inserted use either | |
- * 'parentId' or 'prevId'. | |
- * @return integer the ID of the element that had been inserted | |
- */ | |
- function add($newValues, $parentId = 0, $prevId = 0) | |
- { | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- $prevVisited = 0; | |
- | |
- // check the DB-table if the columns which are given as keys | |
- // in the array $newValues do really exist, if not remove them | |
- // from the array | |
- // FIXXME do the above described | |
- // if no parent and no prevId is given the root shall be added | |
- if ($parentId || $prevId) { | |
- if ($prevId) { | |
- $element = $this->getElement($prevId); | |
- // we also need the parent id of the element | |
- // to write it in the db | |
- $parentId = $element['parentId']; | |
- } else { | |
- $element = $this->getElement($parentId); | |
- } | |
- $newValues['parentId'] = $parentId; | |
- | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- | |
- // get the "visited"-value where to add the new element behind | |
- // if $prevId is given, we need to use the right-value | |
- // if only the $parentId is given we need to use the left-value | |
- // look at it graphically, that made me understand it :-) | |
- // See: | |
- // http://research.calacademy.org/taf/proceedings/ballew/sld034.htm | |
- $prevVisited = $prevId ? $element['right'] : $element['left']; | |
- | |
- // FIXXME start transaction here | |
- if (Tree::isError($err = $this->_add($prevVisited, 1))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- } | |
- | |
- // inserting _one_ new element in the tree | |
- $newData = array(); | |
- // quote the values, as needed for the insert | |
- foreach ($newValues as $key => $value) { | |
- | |
- ///////////FIX ME: Add proper quote handling | |
- | |
- $newData[$this->_getColName($key)] = $this->dbh->getTextValue($value); | |
- } | |
- | |
- // set the proper right and left values | |
- $newData[$lName] = $prevVisited + 1; | |
- $newData[$rName] = $prevVisited + 2; | |
- | |
- // use sequences to create a new id in the db-table | |
- $nextId = $this->dbh->nextId($this->table); | |
- $query = sprintf('INSERT INTO %s (%s,%s) VALUES (%s,%s)', | |
- $this->table, | |
- $this->_getColName('id'), | |
- implode(',', array_keys($newData)) , | |
- $this->dbh->getIntegerValue($nextId), | |
- implode(',', $newData) | |
- ); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // rollback | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- // commit here | |
- | |
- return $nextId; | |
- } | |
- | |
- // }}} | |
- // {{{ _add() | |
- | |
- /** | |
- * this method only updates the left/right values of all the | |
- * elements that are affected by the insertion | |
- * be sure to set the parentId of the element(s) you insert | |
- * | |
- * @param int this parameter is not the ID!!! | |
- * it is the previous visit number, that means | |
- * if you are inserting a child, you need to use the left-value | |
- * of the parent | |
- * if you are inserting a "next" element, on the same level | |
- * you need to give the right value !! | |
- * @param int the number of elements you plan to insert | |
- * @return mixed either true on success or a Tree_Error on failure | |
- */ | |
- function _add($prevVisited, $numberOfElements = 1) | |
- { | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- | |
- // update the elements which will be affected by the new insert | |
- $query = sprintf('UPDATE %s SET %s=%s+%s WHERE%s %s>%s', | |
- $this->table, | |
- $lName, | |
- $lName, | |
- $numberOfElements*2, | |
- $this->_getWhereAddOn(), | |
- $lName, | |
- $prevVisited); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // FIXXME rollback | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- $query = sprintf('UPDATE %s SET %s=%s+%s WHERE%s %s>%s', | |
- $this->table, | |
- $rName,$rName, | |
- $numberOfElements*2, | |
- $this->_getWhereAddOn(), | |
- $rName, | |
- $prevVisited); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // FIXXME rollback | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ remove() | |
- | |
- /** | |
- * remove a tree element | |
- * this automatically remove all children and their children | |
- * if a node shall be removed that has children | |
- * | |
- * @access public | |
- * @param integer $id the id of the element to be removed | |
- * @return boolean returns either true or throws an error | |
- */ | |
- function remove($id) | |
- { | |
- $element = $this->getElement($id); | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- | |
- // FIXXME start transaction | |
- //$this->dbh->autoCommit(false); | |
- $query = sprintf( 'DELETE FROM %s WHERE%s %s BETWEEN %s AND %s', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left'), | |
- $element['left'],$element['right']); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- if (Tree::isError($err = $this->_remove($element))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ _remove() | |
- | |
- /** | |
- * removes a tree element, but only updates the left/right values | |
- * to make it seem as if the given element would not exist anymore | |
- * it doesnt remove the row(s) in the db itself! | |
- * | |
- * @see getElement() | |
- * @access private | |
- * @param array the entire element returned by "getElement" | |
- * @return boolean returns either true or throws an error | |
- */ | |
- function _remove($element) | |
- { | |
- $delta = $element['right'] - $element['left'] + 1; | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- | |
- // update the elements which will be affected by the remove | |
- $query = sprintf("UPDATE | |
- %s | |
- SET | |
- %s=%s-$delta, | |
- %s=%s-$delta | |
- WHERE%s %s>%s", | |
- $this->table, | |
- $lName, $lName, | |
- $rName, $rName, | |
- $this->_getWhereAddOn(), | |
- $lName, $element['left']); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // the rollback shall be done by the method calling this one | |
- // since it is only private we can do that | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- $query = sprintf("UPDATE | |
- %s | |
- SET %s=%s-$delta | |
- WHERE | |
- %s %s < %s | |
- AND | |
- %s>%s", | |
- $this->table, | |
- $rName, $rName, | |
- $this->_getWhereAddOn(), | |
- $lName, $element['left'], | |
- $rName, $element['right']); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // the rollback shall be done by the method calling this one | |
- // since it is only private | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- // FIXXME commit: | |
- // should that not also be done in the method calling this one? | |
- // like when an error occurs? | |
- //$this->dbh->commit(); | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ move() | |
- | |
- /** | |
- * move an entry under a given parent or behind a given entry. | |
- * If a newPrevId is given the newParentId is dismissed! | |
- * call it either like this: | |
- * $tree->move(x, y) | |
- * to move the element (or entire tree) with the id x | |
- * under the element with the id y | |
- * or | |
- * $tree->move(x, 0, y); // ommit the second parameter by setting | |
- * it to 0 | |
- * to move the element (or entire tree) with the id x | |
- * behind the element with the id y | |
- * or | |
- * $tree->move(array(x1,x2,x3), ... | |
- * the first parameter can also be an array of elements that shall | |
- * be moved. the second and third para can be as described above. | |
- * | |
- * If you are using the Memory_DBnested then this method would be invain, | |
- * since Memory.php already does the looping through multiple elements. | |
- * But if Dynamic_DBnested is used we need to do the looping here | |
- * | |
- * @version 2002/06/08 | |
- * @access public | |
- * @param integer the id(s) of the element(s) that shall be moved | |
- * @param integer the id of the element which will be the new parent | |
- * @param integer if prevId is given the element with the id idToMove | |
- * shall be moved _behind_ the element with id=prevId | |
- * if it is 0 it will be put at the beginning | |
- * @return mixed true for success, Tree_Error on failure | |
- */ | |
- function move($idsToMove, $newParentId, $newPrevId = 0) | |
- { | |
- settype($idsToMove,'array'); | |
- $errors = array(); | |
- foreach ($idsToMove as $idToMove) { | |
- $ret = $this->_move($idToMove, $newParentId, $newPrevId); | |
- if (Tree::isError($ret)) { | |
- $errors[] = $ret; | |
- } | |
- } | |
- // FIXXME the error in a nicer way, or even better | |
- // let the throwError method do it!!! | |
- if (sizeof($errors)) { | |
- return $this->_throwError(serialize($errors), __LINE__); | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ _move() | |
- | |
- /** | |
- * this method moves one tree element | |
- * | |
- * @see move() | |
- * @version 2002/04/29 | |
- * @access public | |
- * @param integer the id of the element that shall be moved | |
- * @param integer the id of the element which will be the new parent | |
- * @param integer if prevId is given the element with the id idToMove | |
- * shall be moved _behind_ the element with id=prevId | |
- * if it is 0 it will be put at the beginning | |
- * @return mixed true for success, Tree_Error on failure | |
- */ | |
- function _move($idToMove, $newParentId, $newPrevId = 0) | |
- { | |
- // do some integrity checks first | |
- if ($newPrevId) { | |
- // dont let people move an element behind itself, tell it | |
- // succeeded, since it already is there :-) | |
- if ($newPrevId == $idToMove) { | |
- return true; | |
- } | |
- if (Tree::isError($newPrevious=$this->getElement($newPrevId))) { | |
- return $newPrevious; | |
- } | |
- $newParentId = $newPrevious['parentId']; | |
- } else { | |
- if ($newParentId == 0) { | |
- return $this->_throwError('no parent id given', __LINE__); | |
- } | |
- // if the element shall be moved under one of its children | |
- // return false | |
- if ($this->isChildOf($idToMove,$newParentId)) { | |
- return $this->_throwError( | |
- 'can not move an element under one of its children' , | |
- __LINE__ | |
- ); | |
- } | |
- // dont do anything to let an element be moved under itself | |
- // which is bullshit | |
- if ($newParentId==$idToMove) { | |
- return true; | |
- } | |
- // try to retreive the data of the parent element | |
- if (Tree::isError($newParent=$this->getElement($newParentId))) { | |
- return $newParent; | |
- } | |
- } | |
- // get the data of the element itself | |
- if (Tree::isError($element=$this->getElement($idToMove))) { | |
- return $element; | |
- } | |
- | |
- $numberOfElements = ($element['right'] - $element['left'] + 1) / 2; | |
- $prevVisited = $newPrevId ? $newPrevious['right'] : $newParent['left']; | |
- | |
- // FIXXME start transaction | |
- | |
- // add the left/right values in the new parent, to have the space | |
- // to move the new values in | |
- $err=$this->_add($prevVisited, $numberOfElements); | |
- if (Tree::isError($err)) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- | |
- // update the parentId of the element with $idToMove | |
- $err = $this->update($idToMove, array('parentId' => $newParentId)); | |
- if (Tree::isError($err)) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- | |
- // update the lefts and rights of those elements that shall be moved | |
- | |
- // first get the offset we need to add to the left/right values | |
- // if $newPrevId is given we need to get the right value, | |
- // otherwise the left since the left/right has changed | |
- // because we already updated it up there. We need to get them again. | |
- // We have to do that anyway, to have the proper new left/right values | |
- if ($newPrevId) { | |
- if (Tree::isError($temp = $this->getElement($newPrevId))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $temp; | |
- } | |
- $calcWith = $temp['right']; | |
- } else { | |
- if (Tree::isError($temp = $this->getElement($newParentId))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $temp; | |
- } | |
- $calcWith = $temp['left']; | |
- } | |
- | |
- // get the element that shall be moved again, since the left and | |
- // right might have changed by the add-call | |
- if (Tree::isError($element=$this->getElement($idToMove))) { | |
- return $element; | |
- } | |
- // calc the offset that the element to move has | |
- // to the spot where it should go | |
- $offset = $calcWith - $element['left']; | |
- // correct the offset by one, since it needs to go inbetween! | |
- $offset++; | |
- | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- $query = sprintf("UPDATE | |
- %s | |
- SET | |
- %s=%s+$offset, | |
- %s=%s+$offset | |
- WHERE | |
- %s %s>%s | |
- AND | |
- %s < %s", | |
- $this->table, | |
- $rName, $rName, | |
- $lName, $lName, | |
- $this->_getWhereAddOn(), | |
- $lName, $element['left']-1, | |
- $rName, $element['right']+1); | |
- if (MDB::isError($res=$this->dbh->query($query))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- // remove the part of the tree where the element(s) was/were before | |
- if (Tree::isError($err=$this->_remove($element))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- // FIXXME commit all changes | |
- //$this->dbh->commit(); | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ update() | |
- | |
- /** | |
- * update the tree element given by $id with the values in $newValues | |
- * | |
- * @access public | |
- * @param int the id of the element to update | |
- * @param array the new values, the index is the col name | |
- * @return mixed either true or an Tree_Error | |
- */ | |
- function update($id, $newValues) | |
- { | |
- // just to be sure nothing gets screwed up :-) | |
- unset($newValues[$this->_getColName('left')]); | |
- unset($newValues[$this->_getColName('right')]); | |
- unset($newValues[$this->_getColName('parentId')]); | |
- | |
- // updating _one_ element in the tree | |
- $values = array(); | |
- foreach ($newValues as $key=>$value) { | |
- | |
- | |
- ///////////FIX ME: Add proper quote handling | |
- | |
- | |
- $values[] = $this->_getColName($key).'='.$this->dbh->getTextValue($value); | |
- } | |
- $query = sprintf('UPDATE %s SET %s WHERE%s %s=%s', | |
- $this->table, | |
- implode(',',$values), | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB::isError($res=$this->dbh->query($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ update() | |
- | |
- /** | |
- * copy a subtree/node/... under a new parent or/and behind a given element | |
- * | |
- * | |
- * @access public | |
- * @param integer the ID of the node that shall be copied | |
- * @param integer the new parent ID | |
- * @param integer the new previous ID, if given parent ID will be omitted | |
- * @return boolean true on success | |
- */ | |
- function copy($id, $parentId = 0, $prevId = 0) | |
- { | |
- return $this->_throwError( | |
- 'copy-method is not implemented yet!' , | |
- __LINE__ | |
- ); | |
- // get element tree | |
- // $this->addTree | |
- } | |
- | |
- // }}} | |
- // {{{ getRoot() | |
- | |
- /** | |
- * get the root | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @return mixed either the data of the root element or an Tree_Error | |
- */ | |
- function getRoot() | |
- { | |
- $query = sprintf('SELECT * FROM %s WHERE%s %s=1', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left')); | |
- if (MDB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return !$res ? false : $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getElement() | |
- | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element to return | |
- * | |
- * @return mixed either the data of the requested element | |
- * or an Tree_Error | |
- */ | |
- function getElement($id) | |
- { | |
- $query = sprintf('SELECT * FROM %s WHERE %s %s=%s', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- if (!$res) { | |
- return $this->_throwError("Element with id $id does not exist!" , | |
- __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getChild() | |
- | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @param integer the ID of the element for which the children | |
- * shall be returned | |
- * @return mixed either the data of the requested element or an Tree_Error | |
- */ | |
- function getChild($id) | |
- { | |
- // subqueries would be cool :-) | |
- $curElement = $this->getElement($id); | |
- if (Tree::isError($curElement)) { | |
- return $curElement; | |
- } | |
- | |
- $query = sprintf('SELECT * FROM %s WHERE%s %s=%s', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left'), | |
- $curElement['left']+1); | |
- if (MDB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getPath() | |
- | |
- /** | |
- * gets the path from the element with the given id down | |
- * to the root. The returned array is sorted to start at root | |
- * for simply walking through and retreiving the path | |
- * | |
- * @access public | |
- * @param integer the ID of the element for which the path shall be returned | |
- * @return mixed either the data of the requested elements | |
- * or an Tree_Error | |
- */ | |
- function getPath($id) | |
- { | |
- $res = $this->dbh->getAll($this->_getPathQuery($id)); | |
- if (MDB::isError($res)) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResults($res); | |
- } | |
- | |
- // }}} | |
- // {{{ _getPathQuery() | |
- | |
- function _getPathQuery($id) | |
- { | |
- // subqueries would be cool :-) | |
- $curElement = $this->getElement($id); | |
- $query = sprintf('SELECT * FROM %s '. | |
- 'WHERE %s %s<=%s AND %s>=%s '. | |
- 'ORDER BY %s', | |
- // set the FROM %s | |
- $this->table, | |
- // set the additional where add on | |
- $this->_getWhereAddOn(), | |
- // render 'left<=curLeft' | |
- $this->_getColName('left'), $curElement['left'], | |
- // render right>=curRight' | |
- $this->_getColName('right'), $curElement['right'], | |
- // set the order column | |
- $this->_getColName('left')); | |
- return $query; | |
- } | |
- | |
- // }}} | |
- // {{{ getLevel() | |
- | |
- function getLevel($id) | |
- { | |
- $query = $this->_getPathQuery($id); | |
- // i know this is not really beautiful ... | |
- $query = preg_replace('/^select \* /i','SELECT COUNT(*) ',$query); | |
- if (MDB::isError($res = $this->dbh->getOne($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $res-1; | |
- } | |
- | |
- // }}} | |
- // {{{ getLeft() | |
- | |
- /** | |
- * gets the element to the left, the left visit | |
- * | |
- * @access public | |
- * @version 2002/03/07 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed either the data of the requested element | |
- * or an Tree_Error | |
- */ | |
- function getLeft($id) | |
- { | |
- $element = $this->getElement($id); | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- | |
- $query = sprintf('SELECT * FROM %s WHERE%s (%s=%s OR %s=%s)', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('right'), $element['left'] - 1, | |
- $this->_getColName('left'), $element['left'] - 1); | |
- if (MDB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getRight() | |
- | |
- /** | |
- * gets the element to the right, the right visit | |
- * | |
- * @access public | |
- * @version 2002/03/07 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed either the data of the requested element | |
- * or an Tree_Error | |
- */ | |
- function getRight($id) | |
- { | |
- $element = $this->getElement($id); | |
- if (Tree::isError($element)) | |
- return $element; | |
- | |
- $query = sprintf('SELECT * FROM %s WHERE%s (%s=%s OR %s=%s)', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left'), $element['right'] + 1, | |
- $this->_getColName('right'), $element['right'] + 1); | |
- if (MDB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getParent() | |
- | |
- /** | |
- * get the parent of the element with the given id | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed the array with the data of the parent element | |
- * or false, if there is no parent, if the element is | |
- * the root or an Tree_Error | |
- */ | |
- function getParent($id) | |
- { | |
- $query = sprintf('SELECT | |
- p.* | |
- FROM | |
- %s p,%s e | |
- WHERE | |
- %s e.%s=p.%s | |
- AND | |
- e.%s=%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'p'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getChildren() | |
- | |
- /** | |
- * get the children of the given element or if the parameter is an array. | |
- * It gets the children of all the elements given by their ids | |
- * in the array. | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param mixed (1) int the id of one element | |
- * (2) array an array of ids for which | |
- * the children will be returned | |
- * @param integer the children of how many levels shall be returned | |
- * @return mixed the array with the data of all children | |
- * or false, if there are none | |
- */ | |
- function getChildren($ids, $levels = 1) | |
- { | |
- $res = array(); | |
- for ($i = 1; $i < $levels + 1; $i++) { | |
- // if $ids is an array implode the values | |
- $getIds = is_array($ids) ? implode(',', $ids) : $ids; | |
- | |
- $query = sprintf('SELECT | |
- c.* | |
- FROM | |
- %s c,%s e | |
- WHERE | |
- %s e.%s=c.%s | |
- AND | |
- e.%s IN (%s) '. | |
- 'ORDER BY | |
- c.%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'c'), | |
- $this->_getColName('id'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $getIds, | |
- // order by left, so we have it in the order | |
- // as it is in the tree if no 'order'-option | |
- // is given | |
- $this->getOption('order')? | |
- $this->getOption('order') | |
- : $this->_getColName('left') | |
- ); | |
- if (MDB::isError($_res = $this->dbh->getAll($query))) { | |
- return $this->_throwError($_res->getMessage(), __LINE__); | |
- } | |
- | |
- // Column names are now unmapped | |
- $_res = $this->_prepareResults($_res); | |
- | |
- // we use the id as the index, to make the use easier esp. | |
- // for multiple return-values | |
- $tempRes = array(); | |
- foreach ($_res as $aRes) { | |
- $tempRes[$aRes['id']] = $aRes; | |
- } | |
- $_res = $tempRes; | |
- | |
- if ($levels > 1) { | |
- $ids = array(); | |
- foreach ($_res as $aRes) { | |
- $ids[] = $aRes[$this->_getColName('id')]; | |
- } | |
- } | |
- $res = array_merge($res, $_res); | |
- | |
- // quit the for-loop if there are no children in the current level | |
- if (!sizeof($ids)) { | |
- break; | |
- } | |
- } | |
- return $res; | |
- } | |
- | |
- // }}} | |
- // {{{ getNext() | |
- | |
- /** | |
- * get the next element on the same level | |
- * if there is none return false | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed the array with the data of the next element | |
- * or false, if there is no next | |
- * or Tree_Error | |
- */ | |
- function getNext($id) | |
- { | |
- $query = sprintf('SELECT | |
- n.* | |
- FROM | |
- %s n,%s e | |
- WHERE | |
- %s e.%s=n.%s-1 | |
- AND | |
- e.%s=n.%s | |
- AND | |
- e.%s=%s', | |
- $this->table, $this->table, | |
- $this->_getWhereAddOn(' AND ', 'n'), | |
- $this->_getColName('right'), | |
- $this->_getColName('left'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return !$res ? false : $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getPrevious() | |
- | |
- /** | |
- * get the previous element on the same level | |
- * if there is none return false | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed the array with the data of the previous element | |
- * or false, if there is no previous | |
- * or a Tree_Error | |
- */ | |
- function getPrevious($id) | |
- { | |
- $query = sprintf('SELECT | |
- p.* | |
- FROM | |
- %s p,%s e | |
- WHERE | |
- %s e.%s=p.%s+1 | |
- AND | |
- e.%s=p.%s | |
- AND | |
- e.%s=%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'p'), | |
- $this->_getColName('left'), | |
- $this->_getColName('right'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return !$res ? false : $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ isChildOf() | |
- | |
- /** | |
- * returns if $childId is a child of $id | |
- * | |
- * @abstract | |
- * @version 2002/04/29 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param int id of the element | |
- * @param int id of the element to check if it is a child | |
- * @return boolean true if it is a child | |
- */ | |
- function isChildOf($id, $childId) | |
- { | |
- // check simply if the left and right of the child are within the | |
- // left and right of the parent, if so it definitly is a child :-) | |
- $parent = $this->getElement($id); | |
- $child = $this->getElement($childId); | |
- | |
- if ($parent['left'] < $child['left'] | |
- && $parent['right'] > $child['right']) | |
- { | |
- return true; | |
- } | |
- return false; | |
- } | |
- | |
- // }}} | |
- // {{{ getDepth() | |
- | |
- /** | |
- * return the maximum depth of the tree | |
- * | |
- * @version 2003/02/25 | |
- * @access public | |
- * @author "Denis Joloudov" <[email protected]>, Wolfram Kriesing <[email protected]> | |
- * @return integer the depth of the tree | |
- */ | |
- function getDepth() | |
- { | |
- // FIXXXME TODO!!! | |
- $query = sprintf('SELECT COUNT(*) FROM %s p, %s e '. | |
- 'WHERE %s (e.%s BETWEEN p.%s AND p.%s) AND '. | |
- '(e.%s BETWEEN p.%s AND p.%s)', | |
- $this-> table,$this->table, | |
- // first line in where | |
- $this->_getWhereAddOn(' AND ','p'), | |
- $this->_getColName('left'),$this->_getColName('left'), | |
- $this->_getColName('right'), | |
- // second where line | |
- $this->_getColName('right'),$this->_getColName('left'), | |
- $this->_getColName('right') | |
- ); | |
- if (MDB::isError($res=$this->dbh->getOne($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- if (!$res) { | |
- return false; | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ hasChildren() | |
- | |
- /** | |
- * Tells if the node with the given ID has children. | |
- * | |
- * @version 2003/03/04 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of a node | |
- * @return boolean if the node with the given id has children | |
- */ | |
- function hasChildren($id) | |
- { | |
- $element = $this->getElement($id); | |
- // if the diff between left and right > 1 then there are children | |
- return ($element['right'] - $element['left']) > 1; | |
- } | |
- | |
- // }}} | |
- // {{{ getIdByPath() | |
- | |
- /** | |
- * return the id of the element which is referenced by $path | |
- * this is useful for xml-structures, like: getIdByPath('/root/sub1/sub2') | |
- * this requires the structure to use each name uniquely | |
- * if this is not given it will return the first proper path found | |
- * i.e. there should only be one path /x/y/z | |
- * experimental: the name can be non unique if same names are in different levels | |
- * | |
- * @version 2003/05/11 | |
- * @access public | |
- * @author Pierre-Alain Joye <[email protected]> | |
- * @param string $path the path to search for | |
- * @param integer $startId the id where to start the search | |
- * @param string $nodeName the name of the key that contains | |
- * the node name | |
- * @param string $seperator the path seperator | |
- * @return integer the id of the searched element | |
- */ | |
- function getIdByPath($path, $startId = 0, $nodeName = 'name', $separator = '/') | |
- // should this method be called getElementIdByPath ???? | |
- // Yes, with an optional private paramater to get the whole node | |
- // in preference to only the id? | |
- { | |
- if ($separator == '') { | |
- return $this->_throwError( | |
- 'getIdByPath: Empty separator not allowed', __LINE__); | |
- } | |
- if ($path == $separator) { | |
- $root = $this->getRoot(); | |
- if (Tree::isError($root)) { | |
- return $root; | |
- } | |
- return $root['id']; | |
- } | |
- if (!($colname=$this->_getColName($nodeName))) { | |
- return $this->_throwError( | |
- 'getIdByPath: Invalid node name', __LINE__); | |
- } | |
- if ($startId != 0) { | |
- // If the start node has no child, returns false | |
- // hasChildren calls getElement. Not very good right | |
- // now. See the TODO | |
- $startElem = $this->getElement($startId); | |
- if (!is_array($startElem) || Tree::isError($startElem)) { | |
- return $startElem; | |
- } | |
- // No child? return | |
- if (!is_array($startElem)) { | |
- return null; | |
- } | |
- $rangeStart = $startElem['left']; | |
- $rangeEnd = $startElem['right']; | |
- // Not clean, we should call hasChildren, but I do not | |
- // want to call getELement again :). See TODO | |
- $startHasChild = ($rangeEnd-$rangeStart) > 1 ? true : false; | |
- $cwd = '/'.$this->getPathAsString($startId); | |
- } else { | |
- $cwd = '/'; | |
- $startHasChild = false; | |
- } | |
- $t = $this->_preparePath($path, $cwd, $separator); | |
- if (Tree::isError($t)) { | |
- return $t; | |
- } | |
- list($elems, $sublevels) = $t; | |
- $cntElems = sizeof($elems); | |
- $where = ''; | |
- | |
- $query = 'SELECT ' | |
- .$this->_getColName('id') | |
- .' FROM ' | |
- .$this->table | |
- .' WHERE ' | |
- .$colname; | |
- if ($cntElems == 1) { | |
- $query .= "='".$elems[0]."'"; | |
- } else { | |
- $query .= "='".$elems[$cntElems-1]."'"; | |
- } | |
- if ($startHasChild) { | |
- $where .= ' AND ('. | |
- $this->_getColName('left').'>'.$rangeStart. | |
- ' AND '. | |
- $this->_getColName('right').'<'.$rangeEnd.')'; | |
- } | |
- $res = $this->dbh->getOne($query); | |
- if (MDB::isError($res)) { | |
- return $this->_throwError($res->getMessage(), | |
- __LINE__); | |
- } | |
- return ($res ? (int)$res : false); | |
- } | |
- | |
- // }}} | |
- | |
- // | |
- // PRIVATE METHODS | |
- // | |
- | |
- // {{{ _getWhereAddOn() | |
- /** | |
- * | |
- * | |
- * @access private | |
- * @version 2002/04/20 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param string the current where clause | |
- * @return string the where clause we want to add to a query | |
- */ | |
- function _getWhereAddOn($addAfter = ' AND ', $tableName = '') | |
- { | |
- if ($where=$this->getOption('whereAddOn')) { | |
- return ' '.($tableName ? $tableName.'.' : '')." $where$addAfter "; | |
- } | |
- return ''; | |
- } | |
- | |
- // }}} | |
- // {{{ getFirstRoot() | |
- | |
- // for compatibility to Memory methods | |
- function getFirstRoot() | |
- { | |
- return $this->getRoot(); | |
- } | |
- | |
- // }}} | |
- // {{{ getNode() | |
- | |
- /** | |
- * gets the tree under the given element in one array, sorted | |
- * so you can go through the elements from begin to end and list them | |
- * as they are in the tree, where every child (until the deepest) is retreived | |
- * | |
- * @see &_getNode() | |
- * @access public | |
- * @version 2001/12/17 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer $startId the id where to start walking | |
- * @param integer $depth this number says how deep into | |
- * the structure the elements shall | |
- * be retreived | |
- * @return array sorted as listed in the tree | |
- */ | |
- function &getNode($startId = 0, $depth = 0) | |
- { | |
-//FIXXXME use getChildren() | |
- if ($startId) { | |
- $startNode = $this->getElement($startId); | |
- if (Tree::isError($startNode)) { | |
- return $startNode; | |
- } | |
- | |
- } else { | |
- } | |
- } | |
-} | |
- | |
-/* | |
-* Local Variables: | |
-* mode: php | |
-* tab-width: 4 | |
-* c-basic-offset: 4 | |
-* End: | |
-*/ | |
\ No newline at end of file | |
Index: Tree/Dynamic/MDB2nested.php | |
=================================================================== | |
--- Tree/Dynamic/MDB2nested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Dynamic/MDB2nested.php (.../trunk) (revision 321102) | |
@@ -1,1281 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2004 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/OptionsMDB2.php'; | |
- | |
-/** | |
-* This class implements methods to work on a tree saved using the nested | |
-* tree model. | |
-* explaination: http://research.calacademy.org/taf/proceedings/ballew/index.htm | |
-* | |
-* @access public | |
-* @package Tree | |
-*/ | |
-class Tree_Dynamic_MDB2nested extends Tree_OptionsMDB2 | |
-{ | |
- | |
- // {{{ properties | |
- var $debug = 0; | |
- | |
- var $options = array( | |
- // FIXXME to be implemented | |
- // add on for the where clause, this string is simply added | |
- // behind the WHERE in the select so you better make sure | |
- // its correct SQL :-), i.e. 'uid=3' | |
- // this is needed i.e. when you are saving many trees in one db-table | |
- 'whereAddOn'=>'', | |
- 'table' =>'', | |
- // since the internal names are fixed, to be portable between different | |
- // DB tables with different column namings, we map the internal name | |
- // to the real column name using this array here, if it stays empty | |
- // the internal names are used, which are: | |
- // id, left, right | |
- 'columnNameMaps'=>array( | |
- // since mysql at least doesnt support 'left' ... | |
- 'left' => 'l', | |
- // ...as a column name we set default to the first | |
- //letter only | |
- 'right' => 'r', | |
- // parent id | |
- 'parentId' => 'parent' | |
- ), | |
- // needed for sorting the tree, currently only used in Memory_DBnested | |
- 'order' => '' | |
- ); | |
- | |
- // }}} | |
- // {{{ __construct() | |
- | |
- // the defined methods here are proposals for the implementation, | |
- // they are named the same, as the methods in the "Memory" branch. | |
- // If possible it would be cool to keep the same naming. And | |
- // if the same parameters would be possible too then it would be | |
- // even better, so one could easily change from any kind | |
- // of tree-implementation to another, without changing the source | |
- // code, only the setupXXX would need to be changed | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @param string the DSN for the DB connection | |
- * @return void | |
- */ | |
- function __construct($dsn, $options = array()) | |
- { | |
- $this->Tree_Dynamic_MDB2nested($dsn, $options); | |
- } | |
- | |
- // }}} | |
- // {{{ Tree_Dynamic_DBnested() | |
- | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param string the DSN for the DB connection | |
- * @return void | |
- */ | |
- function Tree_Dynamic_MDB2nested($dsn, $options = array()) | |
- { | |
- parent::Tree_OptionsMDB2($dsn, $options); // instanciate DB | |
- $this->table = $this->getOption('table'); | |
- } | |
- | |
- // }}} | |
- // {{{ add() | |
- | |
- /** | |
- * add a new element to the tree | |
- * there are three ways to use this method | |
- * Method 1: | |
- * Give only the $parentId and the $newValues will be inserted | |
- * as the first child of this parent | |
- * <code> | |
- * // insert a new element under the parent with the ID=7 | |
- * $tree->add(array('name'=>'new element name'), 7); | |
- * </code> | |
- * | |
- * Method 2: | |
- * Give the $prevId ($parentId will be dismissed) and the new element | |
- * will be inserted in the tree after the element with the ID=$prevId | |
- * the parentId is not necessary because the prevId defines exactly where | |
- * the new element has to be place in the tree, and the parent is | |
- * the same as for the element with the ID=$prevId | |
- * <code> | |
- * // insert a new element after the element with the ID=5 | |
- * $tree->add(array('name'=>'new'), 0, 5); | |
- * </code> | |
- * | |
- * Method 3: | |
- * neither $parentId nor prevId is given, then the root element will be | |
- * inserted. This requires that programmer is responsible to confirm this. | |
- * This method does not yet check if there is already a root element saved! | |
- * | |
- * @access public | |
- * @param array $newValues this array contains the values that shall | |
- * be inserted in the db-table | |
- * @param integer $parentId the id of the element which shall be | |
- * the parent of the new element | |
- * @param integer $prevId the id of the element which shall preceed | |
- * the one to be inserted use either | |
- * 'parentId' or 'prevId'. | |
- * @return integer the ID of the element that had been inserted | |
- */ | |
- function add($newValues, $parentId = 0, $prevId = 0) | |
- { | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- $prevVisited = 0; | |
- | |
- // check the DB-table if the columns which are given as keys | |
- // in the array $newValues do really exist, if not remove them | |
- // from the array | |
- // FIXXME do the above described | |
- // if no parent and no prevId is given the root shall be added | |
- if ($parentId || $prevId) { | |
- if ($prevId) { | |
- $element = $this->getElement($prevId); | |
- // we also need the parent id of the element | |
- // to write it in the db | |
- $parentId = $element['parentId']; | |
- } else { | |
- $element = $this->getElement($parentId); | |
- } | |
- $newValues['parentId'] = $parentId; | |
- | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- | |
- // get the "visited"-value where to add the new element behind | |
- // if $prevId is given, we need to use the right-value | |
- // if only the $parentId is given we need to use the left-value | |
- // look at it graphically, that made me understand it :-) | |
- // See: | |
- // http://research.calacademy.org/taf/proceedings/ballew/sld034.htm | |
- $prevVisited = $prevId ? $element['right'] : $element['left']; | |
- | |
- // FIXXME start transaction here | |
- if (Tree::isError($err = $this->_add($prevVisited, 1))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- } | |
- | |
- // inserting _one_ new element in the tree | |
- $newData = array(); | |
- // quote the values, as needed for the insert | |
- foreach ($newValues as $key => $value) { | |
- | |
- ///////////FIX ME: Add proper quote handling | |
- | |
- $newData[$this->_getColName($key)] = $this->dbh->quote($value, 'text'); | |
- } | |
- | |
- // set the proper right and left values | |
- $newData[$lName] = $prevVisited + 1; | |
- $newData[$rName] = $prevVisited + 2; | |
- | |
- // use sequences to create a new id in the db-table | |
- $nextId = $this->dbh->nextId($this->table); | |
- $query = sprintf('INSERT INTO %s (%s,%s) VALUES (%s,%s)', | |
- $this->table, | |
- $this->_getColName('id'), | |
- implode(',', array_keys($newData)) , | |
- $this->dbh->quote($nextId, 'integer'), | |
- implode(',', $newData) | |
- ); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // rollback | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- // commit here | |
- | |
- return $nextId; | |
- } | |
- | |
- // }}} | |
- // {{{ _add() | |
- | |
- /** | |
- * this method only updates the left/right values of all the | |
- * elements that are affected by the insertion | |
- * be sure to set the parentId of the element(s) you insert | |
- * | |
- * @param int this parameter is not the ID!!! | |
- * it is the previous visit number, that means | |
- * if you are inserting a child, you need to use the left-value | |
- * of the parent | |
- * if you are inserting a "next" element, on the same level | |
- * you need to give the right value !! | |
- * @param int the number of elements you plan to insert | |
- * @return mixed either true on success or a Tree_Error on failure | |
- */ | |
- function _add($prevVisited, $numberOfElements = 1) | |
- { | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- | |
- // update the elements which will be affected by the new insert | |
- $query = sprintf('UPDATE %s SET %s=%s+%s WHERE%s %s>%s', | |
- $this->table, | |
- $lName, | |
- $lName, | |
- $numberOfElements*2, | |
- $this->_getWhereAddOn(), | |
- $lName, | |
- $prevVisited); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // FIXXME rollback | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- $query = sprintf('UPDATE %s SET %s=%s+%s WHERE%s %s>%s', | |
- $this->table, | |
- $rName,$rName, | |
- $numberOfElements*2, | |
- $this->_getWhereAddOn(), | |
- $rName, | |
- $prevVisited); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // FIXXME rollback | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ remove() | |
- | |
- /** | |
- * remove a tree element | |
- * this automatically remove all children and their children | |
- * if a node shall be removed that has children | |
- * | |
- * @access public | |
- * @param integer $id the id of the element to be removed | |
- * @return boolean returns either true or throws an error | |
- */ | |
- function remove($id) | |
- { | |
- $element = $this->getElement($id); | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- | |
- // FIXXME start transaction | |
- //$this->dbh->autoCommit(false); | |
- $query = sprintf( 'DELETE FROM %s WHERE%s %s BETWEEN %s AND %s', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left'), | |
- $element['left'],$element['right']); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- if (Tree::isError($err = $this->_remove($element))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ _remove() | |
- | |
- /** | |
- * removes a tree element, but only updates the left/right values | |
- * to make it seem as if the given element would not exist anymore | |
- * it doesnt remove the row(s) in the db itself! | |
- * | |
- * @see getElement() | |
- * @access private | |
- * @param array the entire element returned by "getElement" | |
- * @return boolean returns either true or throws an error | |
- */ | |
- function _remove($element) | |
- { | |
- $delta = $element['right'] - $element['left'] + 1; | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- | |
- // update the elements which will be affected by the remove | |
- $query = sprintf("UPDATE | |
- %s | |
- SET | |
- %s=%s-$delta, | |
- %s=%s-$delta | |
- WHERE%s %s>%s", | |
- $this->table, | |
- $lName, $lName, | |
- $rName, $rName, | |
- $this->_getWhereAddOn(), | |
- $lName, $element['left']); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // the rollback shall be done by the method calling this one | |
- // since it is only private we can do that | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- $query = sprintf("UPDATE | |
- %s | |
- SET %s=%s-$delta | |
- WHERE | |
- %s %s < %s | |
- AND | |
- %s>%s", | |
- $this->table, | |
- $rName, $rName, | |
- $this->_getWhereAddOn(), | |
- $lName, $element['left'], | |
- $rName, $element['right']); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // the rollback shall be done by the method calling this one | |
- // since it is only private | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- // FIXXME commit: | |
- // should that not also be done in the method calling this one? | |
- // like when an error occurs? | |
- //$this->dbh->commit(); | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ move() | |
- | |
- /** | |
- * move an entry under a given parent or behind a given entry. | |
- * If a newPrevId is given the newParentId is dismissed! | |
- * call it either like this: | |
- * $tree->move(x, y) | |
- * to move the element (or entire tree) with the id x | |
- * under the element with the id y | |
- * or | |
- * $tree->move(x, 0, y); // ommit the second parameter by setting | |
- * it to 0 | |
- * to move the element (or entire tree) with the id x | |
- * behind the element with the id y | |
- * or | |
- * $tree->move(array(x1,x2,x3), ... | |
- * the first parameter can also be an array of elements that shall | |
- * be moved. the second and third para can be as described above. | |
- * | |
- * If you are using the Memory_DBnested then this method would be invain, | |
- * since Memory.php already does the looping through multiple elements. | |
- * But if Dynamic_DBnested is used we need to do the looping here | |
- * | |
- * @version 2002/06/08 | |
- * @access public | |
- * @param integer the id(s) of the element(s) that shall be moved | |
- * @param integer the id of the element which will be the new parent | |
- * @param integer if prevId is given the element with the id idToMove | |
- * shall be moved _behind_ the element with id=prevId | |
- * if it is 0 it will be put at the beginning | |
- * @return mixed true for success, Tree_Error on failure | |
- */ | |
- function move($idsToMove, $newParentId, $newPrevId = 0) | |
- { | |
- settype($idsToMove,'array'); | |
- $errors = array(); | |
- foreach ($idsToMove as $idToMove) { | |
- $ret = $this->_move($idToMove, $newParentId, $newPrevId); | |
- if (Tree::isError($ret)) { | |
- $errors[] = $ret; | |
- } | |
- } | |
- // FIXXME the error in a nicer way, or even better | |
- // let the throwError method do it!!! | |
- if (sizeof($errors)) { | |
- return $this->_throwError(serialize($errors), __LINE__); | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ _move() | |
- | |
- /** | |
- * this method moves one tree element | |
- * | |
- * @see move() | |
- * @version 2002/04/29 | |
- * @access public | |
- * @param integer the id of the element that shall be moved | |
- * @param integer the id of the element which will be the new parent | |
- * @param integer if prevId is given the element with the id idToMove | |
- * shall be moved _behind_ the element with id=prevId | |
- * if it is 0 it will be put at the beginning | |
- * @return mixed true for success, Tree_Error on failure | |
- */ | |
- function _move($idToMove, $newParentId, $newPrevId = 0) | |
- { | |
- // do some integrity checks first | |
- if ($newPrevId) { | |
- // dont let people move an element behind itself, tell it | |
- // succeeded, since it already is there :-) | |
- if ($newPrevId == $idToMove) { | |
- return true; | |
- } | |
- if (Tree::isError($newPrevious=$this->getElement($newPrevId))) { | |
- return $newPrevious; | |
- } | |
- $newParentId = $newPrevious['parentId']; | |
- } else { | |
- if ($newParentId == 0) { | |
- return $this->_throwError('no parent id given', __LINE__); | |
- } | |
- // if the element shall be moved under one of its children | |
- // return false | |
- if ($this->isChildOf($idToMove,$newParentId)) { | |
- return $this->_throwError( | |
- 'can not move an element under one of its children', | |
- __LINE__ | |
- ); | |
- } | |
- // dont do anything to let an element be moved under itself | |
- // which is bullshit | |
- if ($newParentId==$idToMove) { | |
- return true; | |
- } | |
- // try to retreive the data of the parent element | |
- if (Tree::isError($newParent = $this->getElement($newParentId))) { | |
- return $newParent; | |
- } | |
- } | |
- // get the data of the element itself | |
- if (Tree::isError($element = $this->getElement($idToMove))) { | |
- return $element; | |
- } | |
- | |
- $numberOfElements = ($element['right'] - $element['left'] + 1) / 2; | |
- $prevVisited = $newPrevId ? $newPrevious['right'] : $newParent['left']; | |
- | |
- // FIXXME start transaction | |
- | |
- // add the left/right values in the new parent, to have the space | |
- // to move the new values in | |
- $err=$this->_add($prevVisited, $numberOfElements); | |
- if (Tree::isError($err)) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- | |
- // update the parentId of the element with $idToMove | |
- $err = $this->update($idToMove, array('parentId' => $newParentId)); | |
- if (Tree::isError($err)) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- | |
- // update the lefts and rights of those elements that shall be moved | |
- | |
- // first get the offset we need to add to the left/right values | |
- // if $newPrevId is given we need to get the right value, | |
- // otherwise the left since the left/right has changed | |
- // because we already updated it up there. We need to get them again. | |
- // We have to do that anyway, to have the proper new left/right values | |
- if ($newPrevId) { | |
- if (Tree::isError($temp = $this->getElement($newPrevId))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $temp; | |
- } | |
- $calcWith = $temp['right']; | |
- } else { | |
- if (Tree::isError($temp = $this->getElement($newParentId))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $temp; | |
- } | |
- $calcWith = $temp['left']; | |
- } | |
- | |
- // get the element that shall be moved again, since the left and | |
- // right might have changed by the add-call | |
- if (Tree::isError($element = $this->getElement($idToMove))) { | |
- return $element; | |
- } | |
- // calc the offset that the element to move has | |
- // to the spot where it should go | |
- $offset = $calcWith - $element['left']; | |
- // correct the offset by one, since it needs to go inbetween! | |
- $offset++; | |
- | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- $query = sprintf("UPDATE | |
- %s | |
- SET | |
- %s=%s+$offset, | |
- %s=%s+$offset | |
- WHERE | |
- %s %s>%s | |
- AND | |
- %s < %s", | |
- $this->table, | |
- $rName, $rName, | |
- $lName, $lName, | |
- $this->_getWhereAddOn(), | |
- $lName, $element['left']-1, | |
- $rName, $element['right']+1); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- // remove the part of the tree where the element(s) was/were before | |
- if (Tree::isError($err = $this->_remove($element))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- // FIXXME commit all changes | |
- //$this->dbh->commit(); | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ update() | |
- | |
- /** | |
- * update the tree element given by $id with the values in $newValues | |
- * | |
- * @access public | |
- * @param int the id of the element to update | |
- * @param array the new values, the index is the col name | |
- * @return mixed either true or an Tree_Error | |
- */ | |
- function update($id, $newValues) | |
- { | |
- // just to be sure nothing gets screwed up :-) | |
- unset($newValues[$this->_getColName('left')]); | |
- unset($newValues[$this->_getColName('right')]); | |
- unset($newValues[$this->_getColName('parentId')]); | |
- | |
- // updating _one_ element in the tree | |
- $values = array(); | |
- foreach ($newValues as $key=>$value) { | |
- | |
- | |
- ///////////FIX ME: Add proper quote handling | |
- | |
- | |
- $values[] = $this->_getColName($key).'='.$this->dbh->quote($value, 'text'); | |
- } | |
- $query = sprintf('UPDATE %s SET %s WHERE%s %s=%s', | |
- $this->table, | |
- implode(',',$values), | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ update() | |
- | |
- /** | |
- * copy a subtree/node/... under a new parent or/and behind a given element | |
- * | |
- * | |
- * @access public | |
- * @param integer the ID of the node that shall be copied | |
- * @param integer the new parent ID | |
- * @param integer the new previous ID, if given parent ID will be omitted | |
- * @return boolean true on success | |
- */ | |
- function copy($id, $parentId = 0, $prevId = 0) | |
- { | |
- return $this->_throwError( | |
- 'copy-method is not implemented yet!', | |
- __LINE__ | |
- ); | |
- // get element tree | |
- // $this->addTree | |
- } | |
- | |
- // }}} | |
- // {{{ getRoot() | |
- | |
- /** | |
- * get the root | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @return mixed either the data of the root element or an Tree_Error | |
- */ | |
- function getRoot() | |
- { | |
- $query = sprintf('SELECT * FROM %s WHERE%s %s=1', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left')); | |
- if (MDB2::isError($res = $this->dbh->queryRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return !$res ? false : $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getElement() | |
- | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element to return | |
- * | |
- * @return mixed either the data of the requested element | |
- * or an Tree_Error | |
- */ | |
- function getElement($id) | |
- { | |
- $query = sprintf('SELECT * FROM %s WHERE %s %s=%s', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB2::isError($res = $this->dbh->queryRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- if (!$res) { | |
- return $this->_throwError("Element with id $id does not exist!", __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getChild() | |
- | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @param integer the ID of the element for which the children | |
- * shall be returned | |
- * @return mixed either the data of the requested element or an Tree_Error | |
- */ | |
- function getChild($id) | |
- { | |
- // subqueries would be cool :-) | |
- $curElement = $this->getElement($id); | |
- if (Tree::isError($curElement)) { | |
- return $curElement; | |
- } | |
- | |
- $query = sprintf('SELECT * FROM %s WHERE%s %s=%s', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left'), | |
- $curElement['left']+1); | |
- if (MDB2::isError($res = $this->dbh->queryRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getPath() | |
- | |
- /** | |
- * gets the path from the element with the given id down | |
- * to the root. The returned array is sorted to start at root | |
- * for simply walking through and retreiving the path | |
- * | |
- * @access public | |
- * @param integer the ID of the element for which the path shall be returned | |
- * @return mixed either the data of the requested elements | |
- * or an Tree_Error | |
- */ | |
- function getPath($id) | |
- { | |
- $res = $this->dbh->queryAll($this->_getPathQuery($id)); | |
- if (MDB2::isError($res)) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResults($res); | |
- } | |
- | |
- // }}} | |
- // {{{ _getPathQuery() | |
- | |
- function _getPathQuery($id) | |
- { | |
- // subqueries would be cool :-) | |
- $curElement = $this->getElement($id); | |
- $query = sprintf('SELECT * FROM %s '. | |
- 'WHERE %s %s<=%s AND %s>=%s '. | |
- 'ORDER BY %s', | |
- // set the FROM %s | |
- $this->table, | |
- // set the additional where add on | |
- $this->_getWhereAddOn(), | |
- // render 'left<=curLeft' | |
- $this->_getColName('left'), $curElement['left'], | |
- // render right>=curRight' | |
- $this->_getColName('right'), $curElement['right'], | |
- // set the order column | |
- $this->_getColName('left')); | |
- return $query; | |
- } | |
- | |
- // }}} | |
- // {{{ getLevel() | |
- | |
- function getLevel($id) | |
- { | |
- $query = $this->_getPathQuery($id); | |
- // i know this is not really beautiful ... | |
- $query = preg_replace('/^select \* /i','SELECT COUNT(*) ',$query); | |
- if (MDB2::isError($res = $this->dbh->queryOne($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $res-1; | |
- } | |
- | |
- // }}} | |
- // {{{ getLeft() | |
- | |
- /** | |
- * gets the element to the left, the left visit | |
- * | |
- * @access public | |
- * @version 2002/03/07 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed either the data of the requested element | |
- * or an Tree_Error | |
- */ | |
- function getLeft($id) | |
- { | |
- $element = $this->getElement($id); | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- | |
- $query = sprintf('SELECT * FROM %s WHERE%s (%s=%s OR %s=%s)', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('right'), $element['left'] - 1, | |
- $this->_getColName('left'), $element['left'] - 1); | |
- if (MDB2::isError($res = $this->dbh->queryRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getRight() | |
- | |
- /** | |
- * gets the element to the right, the right visit | |
- * | |
- * @access public | |
- * @version 2002/03/07 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed either the data of the requested element | |
- * or an Tree_Error | |
- */ | |
- function getRight($id) | |
- { | |
- $element = $this->getElement($id); | |
- if (Tree::isError($element)) | |
- return $element; | |
- | |
- $query = sprintf('SELECT * FROM %s WHERE%s (%s=%s OR %s=%s)', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left'), $element['right'] + 1, | |
- $this->_getColName('right'), $element['right'] + 1); | |
- if (MDB2::isError($res = $this->dbh->queryRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getParent() | |
- | |
- /** | |
- * get the parent of the element with the given id | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed the array with the data of the parent element | |
- * or false, if there is no parent, if the element is | |
- * the root or an Tree_Error | |
- */ | |
- function getParent($id) | |
- { | |
- $query = sprintf('SELECT | |
- p.* | |
- FROM | |
- %s p,%s e | |
- WHERE | |
- %s e.%s=p.%s | |
- AND | |
- e.%s=%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'p'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB2::isError($res = $this->dbh->queryRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getChildren() | |
- | |
- /** | |
- * get the children of the given element or if the parameter is an array. | |
- * It gets the children of all the elements given by their ids | |
- * in the array. | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param mixed (1) int the id of one element | |
- * (2) array an array of ids for which | |
- * the children will be returned | |
- * @param integer the children of how many levels shall be returned | |
- * @return mixed the array with the data of all children | |
- * or false, if there are none | |
- */ | |
- function getChildren($ids, $levels = 1) | |
- { | |
- $res = array(); | |
- for ($i = 1; $i < $levels + 1; $i++) { | |
- // if $ids is an array implode the values | |
- $getIds = is_array($ids) ? implode(',', $ids) : $ids; | |
- | |
- $query = sprintf('SELECT | |
- c.* | |
- FROM | |
- %s c,%s e | |
- WHERE | |
- %s e.%s=c.%s | |
- AND | |
- e.%s IN (%s) '. | |
- 'ORDER BY | |
- c.%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'c'), | |
- $this->_getColName('id'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $getIds, | |
- // order by left, so we have it in the order | |
- // as it is in the tree if no 'order'-option | |
- // is given | |
- $this->getOption('order')? | |
- $this->getOption('order') | |
- : $this->_getColName('left') | |
- ); | |
- if (MDB2::isError($_res = $this->dbh->queryAll($query))) { | |
- return $this->_throwError($_res->getMessage(), __LINE__); | |
- } | |
- | |
- // Column names are now unmapped | |
- $_res = $this->_prepareResults($_res); | |
- | |
- // we use the id as the index, to make the use easier esp. | |
- // for multiple return-values | |
- $tempRes = array(); | |
- foreach ($_res as $aRes) { | |
- $tempRes[$aRes['id']] = $aRes; | |
- } | |
- $_res = $tempRes; | |
- | |
- if ($levels > 1) { | |
- $ids = array(); | |
- foreach ($_res as $aRes) { | |
- $ids[] = $aRes[$this->_getColName('id')]; | |
- } | |
- } | |
- $res = array_merge($res, $_res); | |
- | |
- // quit the for-loop if there are no children in the current level | |
- if (!sizeof($ids)) { | |
- break; | |
- } | |
- } | |
- return $res; | |
- } | |
- | |
- // }}} | |
- // {{{ getNext() | |
- | |
- /** | |
- * get the next element on the same level | |
- * if there is none return false | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed the array with the data of the next element | |
- * or false, if there is no next | |
- * or Tree_Error | |
- */ | |
- function getNext($id) | |
- { | |
- $query = sprintf('SELECT | |
- n.* | |
- FROM | |
- %s n,%s e | |
- WHERE | |
- %s e.%s=n.%s-1 | |
- AND | |
- e.%s=n.%s | |
- AND | |
- e.%s=%s', | |
- $this->table, $this->table, | |
- $this->_getWhereAddOn(' AND ', 'n'), | |
- $this->_getColName('right'), | |
- $this->_getColName('left'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB2::isError($res = $this->dbh->queryRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return !$res ? false : $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getPrevious() | |
- | |
- /** | |
- * get the previous element on the same level | |
- * if there is none return false | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed the array with the data of the previous element | |
- * or false, if there is no previous | |
- * or a Tree_Error | |
- */ | |
- function getPrevious($id) | |
- { | |
- $query = sprintf('SELECT | |
- p.* | |
- FROM | |
- %s p,%s e | |
- WHERE | |
- %s e.%s=p.%s+1 | |
- AND | |
- e.%s=p.%s | |
- AND | |
- e.%s=%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'p'), | |
- $this->_getColName('left'), | |
- $this->_getColName('right'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $id); | |
- if (MDB2::isError($res = $this->dbh->queryRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return !$res ? false : $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ isChildOf() | |
- | |
- /** | |
- * returns if $childId is a child of $id | |
- * | |
- * @abstract | |
- * @version 2002/04/29 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param int id of the element | |
- * @param int id of the element to check if it is a child | |
- * @return boolean true if it is a child | |
- */ | |
- function isChildOf($id, $childId) | |
- { | |
- // check simply if the left and right of the child are within the | |
- // left and right of the parent, if so it definitly is a child :-) | |
- $parent = $this->getElement($id); | |
- $child = $this->getElement($childId); | |
- | |
- if ($parent['left'] < $child['left'] | |
- && $parent['right'] > $child['right']) | |
- { | |
- return true; | |
- } | |
- return false; | |
- } | |
- | |
- // }}} | |
- // {{{ getDepth() | |
- | |
- /** | |
- * return the maximum depth of the tree | |
- * | |
- * @version 2003/02/25 | |
- * @access public | |
- * @author "Denis Joloudov" <[email protected]>, Wolfram Kriesing <[email protected]> | |
- * @return integer the depth of the tree | |
- */ | |
- function getDepth() | |
- { | |
- // FIXXXME TODO!!! | |
- $query = sprintf('SELECT COUNT(*) FROM %s p, %s e '. | |
- 'WHERE %s (e.%s BETWEEN p.%s AND p.%s) AND '. | |
- '(e.%s BETWEEN p.%s AND p.%s)', | |
- $this-> table,$this->table, | |
- // first line in where | |
- $this->_getWhereAddOn(' AND ','p'), | |
- $this->_getColName('left'),$this->_getColName('left'), | |
- $this->_getColName('right'), | |
- // second where line | |
- $this->_getColName('right'),$this->_getColName('left'), | |
- $this->_getColName('right') | |
- ); | |
- if (MDB2::isError($res=$this->dbh->queryOne($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- if (!$res) { | |
- return false; | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ hasChildren() | |
- | |
- /** | |
- * Tells if the node with the given ID has children. | |
- * | |
- * @version 2003/03/04 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of a node | |
- * @return boolean if the node with the given id has children | |
- */ | |
- function hasChildren($id) | |
- { | |
- $element = $this->getElement($id); | |
- // if the diff between left and right > 1 then there are children | |
- return ($element['right'] - $element['left']) > 1; | |
- } | |
- | |
- // }}} | |
- // {{{ getIdByPath() | |
- | |
- /** | |
- * return the id of the element which is referenced by $path | |
- * this is useful for xml-structures, like: getIdByPath('/root/sub1/sub2') | |
- * this requires the structure to use each name uniquely | |
- * if this is not given it will return the first proper path found | |
- * i.e. there should only be one path /x/y/z | |
- * experimental: the name can be non unique if same names are in different levels | |
- * | |
- * @version 2003/05/11 | |
- * @access public | |
- * @author Pierre-Alain Joye <[email protected]> | |
- * @param string $path the path to search for | |
- * @param integer $startId the id where to start the search | |
- * @param string $nodeName the name of the key that contains | |
- * the node name | |
- * @param string $seperator the path seperator | |
- * @return integer the id of the searched element | |
- */ | |
- function getIdByPath($path, $startId = 0, $nodeName = 'name', $separator = '/') | |
- // should this method be called getElementIdByPath ???? | |
- // Yes, with an optional private paramater to get the whole node | |
- // in preference to only the id? | |
- { | |
- if ($separator == '') { | |
- return $this->_throwError( | |
- 'getIdByPath: Empty separator not allowed', __LINE__); | |
- } | |
- if ($path == $separator) { | |
- $root = $this->getRoot(); | |
- if (Tree::isError($root)) { | |
- return $root; | |
- } | |
- return $root['id']; | |
- } | |
- if (!($colname=$this->_getColName($nodeName))) { | |
- return $this->_throwError( | |
- 'getIdByPath: Invalid node name', __LINE__); | |
- } | |
- if ($startId != 0) { | |
- // If the start node has no child, returns false | |
- // hasChildren calls getElement. Not very good right | |
- // now. See the TODO | |
- $startElem = $this->getElement($startId); | |
- if (!is_array($startElem) || Tree::isError($startElem)) { | |
- return $startElem; | |
- } | |
- // No child? return | |
- if (!is_array($startElem)) { | |
- return null; | |
- } | |
- $rangeStart = $startElem['left']; | |
- $rangeEnd = $startElem['right']; | |
- // Not clean, we should call hasChildren, but I do not | |
- // want to call getELement again :). See TODO | |
- $startHasChild = ($rangeEnd-$rangeStart) > 1 ? true : false; | |
- $cwd = '/'.$this->getPathAsString($startId); | |
- } else { | |
- $cwd = '/'; | |
- $startHasChild = false; | |
- } | |
- $t = $this->_preparePath($path, $cwd, $separator); | |
- if (Tree::isError($t)) { | |
- return $t; | |
- } | |
- list($elems, $sublevels) = $t; | |
- $cntElems = sizeof($elems); | |
- $where = ''; | |
- | |
- $query = 'SELECT ' | |
- .$this->_getColName('id') | |
- .' FROM ' | |
- .$this->table | |
- .' WHERE ' | |
- .$colname; | |
- if ($cntElems == 1) { | |
- $query .= "='".$elems[0]."'"; | |
- } else { | |
- $query .= "='".$elems[$cntElems-1]."'"; | |
- } | |
- if ($startHasChild) { | |
- $where .= ' AND ('. | |
- $this->_getColName('left').'>'.$rangeStart. | |
- ' AND '. | |
- $this->_getColName('right').'<'.$rangeEnd.')'; | |
- } | |
- $res = $this->dbh->queryOne($query); | |
- if (MDB2::isError($res)) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return ($res ? (int)$res : false); | |
- } | |
- | |
- // }}} | |
- | |
- // | |
- // PRIVATE METHODS | |
- // | |
- | |
- // {{{ _getWhereAddOn() | |
- /** | |
- * | |
- * | |
- * @access private | |
- * @version 2002/04/20 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param string the current where clause | |
- * @return string the where clause we want to add to a query | |
- */ | |
- function _getWhereAddOn($addAfter = ' AND ', $tableName = '') | |
- { | |
- if ($where=$this->getOption('whereAddOn')) { | |
- return ' '.($tableName ? $tableName.'.' : '')." $where$addAfter "; | |
- } | |
- return ''; | |
- } | |
- | |
- // }}} | |
- // {{{ getFirstRoot() | |
- | |
- // for compatibility to Memory methods | |
- function getFirstRoot() | |
- { | |
- return $this->getRoot(); | |
- } | |
- | |
- // }}} | |
- // {{{ getNode() | |
- | |
- /** | |
- * gets the tree under the given element in one array, sorted | |
- * so you can go through the elements from begin to end and list them | |
- * as they are in the tree, where every child (until the deepest) is retreived | |
- * | |
- * @see &_getNode() | |
- * @access public | |
- * @version 2001/12/17 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer $startId the id where to start walking | |
- * @param integer $depth this number says how deep into | |
- * the structure the elements shall | |
- * be retreived | |
- * @return array sorted as listed in the tree | |
- */ | |
- function &getNode($startId = 0, $depth = 0) | |
- { | |
-//FIXXXME use getChildren() | |
- if ($startId) { | |
- $startNode = $this->getElement($startId); | |
- if (Tree::isError($startNode)) { | |
- return $startNode; | |
- } | |
- | |
- } else { | |
- } | |
- } | |
-} | |
- | |
-/* | |
-* Local Variables: | |
-* mode: php | |
-* tab-width: 4 | |
-* c-basic-offset: 4 | |
-* End: | |
-*/ | |
\ No newline at end of file | |
Index: Tree/Dynamic/DBnested.php | |
=================================================================== | |
--- Tree/Dynamic/DBnested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Dynamic/DBnested.php (.../trunk) (revision 321102) | |
@@ -1,1287 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/OptionsDB.php'; | |
- | |
-/** | |
- * This class implements methods to work on a tree saved using the nested | |
- * tree model. | |
- * explaination: http://research.calacademy.org/taf/proceedings/ballew/index.htm | |
- * | |
- * @access public | |
- * @package Tree | |
- */ | |
-class Tree_Dynamic_DBnested extends Tree_OptionsDB | |
-{ | |
- | |
- // {{{ properties | |
- var $debug = 0; | |
- | |
- var $options = array( | |
- // FIXXME to be implemented | |
- // add on for the where clause, this string is simply added | |
- // behind the WHERE in the select so you better make sure | |
- // its correct SQL :-), i.e. 'uid=3' | |
- // this is needed i.e. when you are saving many trees in one db-table | |
- 'whereAddOn'=>'', | |
- 'table' =>'', | |
- // since the internal names are fixed, to be portable between different | |
- // DB tables with different column namings, we map the internal name | |
- // to the real column name using this array here, if it stays empty | |
- // the internal names are used, which are: | |
- // id, left, right | |
- 'columnNameMaps'=>array( | |
- // since mysql at least doesnt support 'left' ... | |
- 'left' => 'l', | |
- // ...as a column name we set default to the first | |
- //letter only | |
- 'right' => 'r', | |
- // parent id | |
- 'parentId' => 'parent' | |
- ), | |
- // needed for sorting the tree, currently only used in Memory_DBnested | |
- 'order' => '' | |
- ); | |
- | |
- // }}} | |
- // {{{ __construct() | |
- | |
- // the defined methods here are proposals for the implementation, | |
- // they are named the same, as the methods in the "Memory" branch. | |
- // If possible it would be cool to keep the same naming. And | |
- // if the same parameters would be possible too then it would be | |
- // even better, so one could easily change from any kind | |
- // of tree-implementation to another, without changing the source | |
- // code, only the setupXXX would need to be changed | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param string the DSN for the DB connection | |
- * @return void | |
- */ | |
- function __construct($dsn, $options = array()) | |
- { | |
- $this->Tree_Dynamic_DBnested($dsn, $options); | |
- } | |
- | |
- // }}} | |
- // {{{ Tree_Dynamic_DBnested() | |
- | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param string the DSN for the DB connection | |
- * @return void | |
- */ | |
- function Tree_Dynamic_DBnested($dsn, $options = array()) | |
- { | |
- parent::Tree_OptionsDB($dsn, $options); // instanciate DB | |
- $this->table = $this->getOption('table'); | |
- } | |
- | |
- // }}} | |
- // {{{ add() | |
- | |
- /** | |
- * add a new element to the tree | |
- * there are three ways to use this method | |
- * Method 1: | |
- * Give only the $parentId and the $newValues will be inserted | |
- * as the first child of this parent | |
- * <code> | |
- * // insert a new element under the parent with the ID=7 | |
- * $tree->add(array('name'=>'new element name'), 7); | |
- * </code> | |
- * | |
- * Method 2: | |
- * Give the $prevId ($parentId will be dismissed) and the new element | |
- * will be inserted in the tree after the element with the ID=$prevId | |
- * the parentId is not necessary because the prevId defines exactly where | |
- * the new element has to be place in the tree, and the parent is | |
- * the same as for the element with the ID=$prevId | |
- * <code> | |
- * // insert a new element after the element with the ID=5 | |
- * $tree->add(array('name'=>'new'), 0, 5); | |
- * </code> | |
- * | |
- * Method 3: | |
- * neither $parentId nor prevId is given, then the root element will be | |
- * inserted. This requires that programmer is responsible to confirm this. | |
- * This method does not yet check if there is already a root element saved! | |
- * | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array $newValues this array contains the values that shall | |
- * be inserted in the db-table | |
- * @param integer $parentId the id of the element which shall be | |
- * the parent of the new element | |
- * @param integer $prevId the id of the element which shall preceed | |
- * the one to be inserted use either | |
- * 'parentId' or 'prevId'. | |
- * @return integer the ID of the element that had been inserted | |
- */ | |
- function add($newValues, $parentId = 0, $prevId = 0) | |
- { | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- $prevVisited = 0; | |
- | |
- // check the DB-table if the columns which are given as keys | |
- // in the array $newValues do really exist, if not remove them | |
- // from the array | |
- // FIXXME do the above described | |
- // if no parent and no prevId is given the root shall be added | |
- if ($parentId || $prevId) { | |
- if ($prevId) { | |
- $element = $this->getElement($prevId); | |
- // we also need the parent id of the element | |
- // to write it in the db | |
- $parentId = $element['parentId']; | |
- } else { | |
- $element = $this->getElement($parentId); | |
- } | |
- $newValues['parentId'] = $parentId; | |
- | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- | |
- // get the "visited"-value where to add the new element behind | |
- // if $prevId is given, we need to use the right-value | |
- // if only the $parentId is given we need to use the left-value | |
- // look at it graphically, that made me understand it :-) | |
- // See: | |
- // http://research.calacademy.org/taf/proceedings/ballew/sld034.htm | |
- $prevVisited = $prevId ? $element['right'] : $element['left']; | |
- | |
- // FIXXME start transaction here | |
- if (Tree::isError($err = $this->_add($prevVisited, 1))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- } | |
- | |
- // inserting _one_ new element in the tree | |
- $newData = array(); | |
- // quote the values, as needed for the insert | |
- foreach ($newValues as $key => $value) { | |
- $newData[$this->_getColName($key)] = $this->dbh->quoteSmart($value); | |
- } | |
- | |
- // set the proper right and left values | |
- $newData[$lName] = $prevVisited + 1; | |
- $newData[$rName] = $prevVisited + 2; | |
- | |
- // use sequences to create a new id in the db-table | |
- $nextId = $this->dbh->nextId($this->table); | |
- $query = sprintf('INSERT INTO %s (%s,%s) VALUES (%s,%s)', | |
- $this->table , | |
- $this->_getColName('id'), | |
- implode(',', array_keys($newData)) , | |
- $nextId, | |
- implode(',', $newData) | |
- ); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // rollback | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- // commit here | |
- | |
- return $nextId; | |
- } | |
- | |
- // }}} | |
- // {{{ _add() | |
- | |
- /** | |
- * this method only updates the left/right values of all the | |
- * elements that are affected by the insertion | |
- * be sure to set the parentId of the element(s) you insert | |
- * | |
- * @param int this parameter is not the ID!!! | |
- * it is the previous visit number, that means | |
- * if you are inserting a child, you need to use the left-value | |
- * of the parent | |
- * if you are inserting a "next" element, on the same level | |
- * you need to give the right value !! | |
- * @param int the number of elements you plan to insert | |
- * @return mixed either true on success or a Tree_Error on failure | |
- */ | |
- function _add($prevVisited, $numberOfElements = 1) | |
- { | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- | |
- // update the elements which will be affected by the new insert | |
- $query = sprintf('UPDATE %s SET %s=%s+%s WHERE%s %s>%s', | |
- $this->table, | |
- $lName, | |
- $lName, | |
- $numberOfElements*2, | |
- $this->_getWhereAddOn(), | |
- $lName, | |
- $prevVisited); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // FIXXME rollback | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- $query = sprintf('UPDATE %s SET %s=%s+%s WHERE%s %s>%s', | |
- $this->table, | |
- $rName,$rName, | |
- $numberOfElements*2, | |
- $this->_getWhereAddOn(), | |
- $rName, | |
- $prevVisited); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // FIXXME rollback | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ remove() | |
- | |
- /** | |
- * remove a tree element | |
- * this automatically remove all children and their children | |
- * if a node shall be removed that has children | |
- * | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer $id the id of the element to be removed | |
- * @return boolean returns either true or throws an error | |
- */ | |
- function remove($id) | |
- { | |
- $element = $this->getElement($id); | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- | |
- // FIXXME start transaction | |
- //$this->dbh->autoCommit(false); | |
- $query = sprintf('DELETE FROM %s WHERE%s %s BETWEEN %s AND %s', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left'), | |
- $element['left'],$element['right']); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- if (Tree::isError($err = $this->_remove($element))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ _remove() | |
- | |
- /** | |
- * removes a tree element, but only updates the left/right values | |
- * to make it seem as if the given element would not exist anymore | |
- * it doesnt remove the row(s) in the db itself! | |
- * | |
- * @see getElement() | |
- * @access private | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array the entire element returned by "getElement" | |
- * @return boolean returns either true or throws an error | |
- */ | |
- function _remove($element) | |
- { | |
- $delta = $element['right'] - $element['left'] + 1; | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- | |
- // update the elements which will be affected by the remove | |
- $query = sprintf("UPDATE | |
- %s | |
- SET | |
- %s=%s-$delta, | |
- %s=%s-$delta | |
- WHERE%s %s>%s", | |
- $this->table, | |
- $lName,$lName, | |
- $rName,$rName, | |
- $this->_getWhereAddOn(), | |
- $lName,$element['left']); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // the rollback shall be done by the method calling this one | |
- // since it is only private we can do that | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- $query = sprintf("UPDATE | |
- %s | |
- SET %s=%s-$delta | |
- WHERE | |
- %s %s < %s | |
- AND | |
- %s>%s", | |
- $this->table, | |
- $rName,$rName, | |
- $this->_getWhereAddOn(), | |
- $lName,$element['left'], | |
- $rName,$element['right']); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // the rollback shall be done by the method calling this one | |
- // since it is only private | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- // FIXXME commit: | |
- // should that not also be done in the method calling this one? | |
- // like when an error occurs? | |
- //$this->dbh->commit(); | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ move() | |
- | |
- /** | |
- * move an entry under a given parent or behind a given entry. | |
- * If a newPrevId is given the newParentId is dismissed! | |
- * call it either like this: | |
- * $tree->move(x, y) | |
- * to move the element (or entire tree) with the id x | |
- * under the element with the id y | |
- * or | |
- * $tree->move(x, 0, y); // ommit the second parameter by setting | |
- * it to 0 | |
- * to move the element (or entire tree) with the id x | |
- * behind the element with the id y | |
- * or | |
- * $tree->move(array(x1,x2,x3), ... | |
- * the first parameter can also be an array of elements that shall | |
- * be moved. the second and third para can be as described above. | |
- * | |
- * If you are using the Memory_DBnested then this method would be invain, | |
- * since Memory.php already does the looping through multiple elements. | |
- * But if Dynamic_DBnested is used we need to do the looping here | |
- * | |
- * @version 2002/06/08 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the id(s) of the element(s) that shall be moved | |
- * @param integer the id of the element which will be the new parent | |
- * @param integer if prevId is given the element with the id idToMove | |
- * shall be moved _behind_ the element with id=prevId | |
- * if it is 0 it will be put at the beginning | |
- * @return mixed true for success, Tree_Error on failure | |
- */ | |
- function move($idsToMove, $newParentId, $newPrevId = 0) | |
- { | |
- settype($idsToMove, 'array'); | |
- $errors = array(); | |
- foreach ($idsToMove as $idToMove) { | |
- $ret = $this->_move($idToMove, $newParentId, $newPrevId); | |
- if (Tree::isError($ret)) { | |
- $errors[] = $ret; | |
- } | |
- } | |
- // FIXXME the error in a nicer way, or even better | |
- // let the throwError method do it!!! | |
- if (sizeof($errors)) { | |
- return $this->_throwError(serialize($errors), __LINE__); | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ _move() | |
- | |
- /** | |
- * this method moves one tree element | |
- * | |
- * @see move() | |
- * @version 2002/04/29 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the id of the element that shall be moved | |
- * @param integer the id of the element which will be the new parent | |
- * @param integer if prevId is given the element with the id idToMove | |
- * shall be moved _behind_ the element with id=prevId | |
- * if it is 0 it will be put at the beginning | |
- * @return mixed true for success, Tree_Error on failure | |
- */ | |
- function _move($idToMove, $newParentId, $newPrevId = 0) | |
- { | |
- // do some integrity checks first | |
- if ($newPrevId) { | |
- // dont let people move an element behind itself, tell it | |
- // succeeded, since it already is there :-) | |
- if ($newPrevId == $idToMove) { | |
- return true; | |
- } | |
- if (Tree::isError($newPrevious = $this->getElement($newPrevId))) { | |
- return $newPrevious; | |
- } | |
- $newParentId = $newPrevious['parentId']; | |
- } else { | |
- if ($newParentId == 0) { | |
- return $this->_throwError('no parent id given', __LINE__); | |
- } | |
- // if the element shall be moved under one of its children | |
- // return false | |
- if ($this->isChildOf($idToMove,$newParentId)) { | |
- return $this->_throwError( | |
- 'can not move an element under one of its children' , | |
- __LINE__ | |
- ); | |
- } | |
- // dont do anything to let an element be moved under itself | |
- // which is bullshit | |
- if ($newParentId == $idToMove) { | |
- return true; | |
- } | |
- // try to retreive the data of the parent element | |
- if (Tree::isError($newParent=$this->getElement($newParentId))) { | |
- return $newParent; | |
- } | |
- } | |
- // get the data of the element itself | |
- if (Tree::isError($element=$this->getElement($idToMove))) { | |
- return $element; | |
- } | |
- | |
- $numberOfElements = ($element['right'] - $element['left'] + 1) / 2; | |
- $prevVisited = $newPrevId ? $newPrevious['right'] : $newParent['left']; | |
- | |
- // FIXXME start transaction | |
- | |
- // add the left/right values in the new parent, to have the space | |
- // to move the new values in | |
- $err = $this->_add($prevVisited, $numberOfElements); | |
- if (Tree::isError($err)) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- | |
- // update the parentId of the element with $idToMove | |
- $err = $this->update($idToMove,array('parentId' => $newParentId)); | |
- if (Tree::isError($err)) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- | |
- // update the lefts and rights of those elements that shall be moved | |
- | |
- // first get the offset we need to add to the left/right values | |
- // if $newPrevId is given we need to get the right value, | |
- // otherwise the left since the left/right has changed | |
- // because we already updated it up there. We need to get them again. | |
- // We have to do that anyway, to have the proper new left/right values | |
- if ($newPrevId) { | |
- if (Tree::isError($temp = $this->getElement($newPrevId))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $temp; | |
- } | |
- $calcWith = $temp['right']; | |
- } else { | |
- if (Tree::isError($temp=$this->getElement($newParentId))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $temp; | |
- } | |
- $calcWith = $temp['left']; | |
- } | |
- | |
- // get the element that shall be moved again, since the left and | |
- // right might have changed by the add-call | |
- if (Tree::isError($element=$this->getElement($idToMove))) { | |
- return $element; | |
- } | |
- // calc the offset that the element to move has | |
- // to the spot where it should go | |
- $offset = $calcWith - $element['left']; | |
- // correct the offset by one, since it needs to go inbetween! | |
- $offset++; | |
- | |
- $lName = $this->_getColName('left'); | |
- $rName = $this->_getColName('right'); | |
- $query = sprintf("UPDATE | |
- %s | |
- SET | |
- %s=%s+$offset, | |
- %s=%s+$offset | |
- WHERE | |
- %s %s>%s | |
- AND | |
- %s < %s", | |
- $this->table, | |
- $rName,$rName, | |
- $lName,$lName, | |
- $this->_getWhereAddOn(), | |
- $lName,$element['left']-1, | |
- $rName,$element['right']+1); | |
- if (DB::isError($res=$this->dbh->query($query))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- // remove the part of the tree where the element(s) was/were before | |
- if (Tree::isError($err = $this->_remove($element))) { | |
- // FIXXME rollback | |
- //$this->dbh->rollback(); | |
- return $err; | |
- } | |
- // FIXXME commit all changes | |
- //$this->dbh->commit(); | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ update() | |
- | |
- /** | |
- * update the tree element given by $id with the values in $newValues | |
- * | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param int the id of the element to update | |
- * @param array the new values, the index is the col name | |
- * @return mixed either true or an Tree_Error | |
- */ | |
- function update($id, $newValues) | |
- { | |
- // just to be sure nothing gets screwed up :-) | |
- unset($newValues[$this->_getColName('left')]); | |
- unset($newValues[$this->_getColName('right')]); | |
- unset($newValues[$this->_getColName('parentId')]); | |
- | |
- // updating _one_ element in the tree | |
- $values = array(); | |
- foreach ($newValues as $key => $value) { | |
- $values[] = $this->_getColName($key).'='.$this->dbh->quoteSmart($value); | |
- } | |
- $query = sprintf('UPDATE %s SET %s WHERE%s %s=%s', | |
- $this->table, | |
- implode(',',$values), | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('id'), | |
- $id); | |
- if (DB::isError($res=$this->dbh->query($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ update() | |
- | |
- /** | |
- * copy a subtree/node/... under a new parent or/and behind a given element | |
- * | |
- * | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the node that shall be copied | |
- * @param integer the new parent ID | |
- * @param integer the new previous ID, if given parent ID will be omitted | |
- * @return boolean true on success | |
- */ | |
- function copy($id, $parentId = 0, $prevId = 0) | |
- { | |
- return $this->_throwError( | |
- 'copy-method is not implemented yet!' , | |
- __LINE__ | |
- ); | |
- // get element tree | |
- // $this->addTree | |
- } | |
- | |
- // }}} | |
- // {{{ getRoot() | |
- | |
- /** | |
- * get the root | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @return mixed either the data of the root element or an Tree_Error | |
- */ | |
- function getRoot() | |
- { | |
- $query = sprintf('SELECT * FROM %s WHERE%s %s=1', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left')); | |
- if (DB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return !$res ? false : $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getElement() | |
- | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element to return | |
- * | |
- * @return mixed either the data of the requested element | |
- * or an Tree_Error | |
- */ | |
- function getElement($id) | |
- { | |
- $query = sprintf('SELECT * FROM %s WHERE %s %s=%s', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('id'), | |
- $id); | |
- $res = $this->dbh->getRow($query); | |
- if (DB::isError($res)) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- if (!$res) { | |
- return $this->_throwError("Element with id $id does not exist!" , | |
- __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getChild() | |
- | |
- /** | |
- * | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element for which the children | |
- * shall be returned | |
- * @return mixed either the data of the requested element or an Tree_Error | |
- */ | |
- function getChild($id) | |
- { | |
- // subqueries would be cool :-) | |
- $curElement = $this->getElement($id); | |
- if (Tree::isError($curElement)) { | |
- return $curElement; | |
- } | |
- | |
- $query = sprintf('SELECT * FROM %s WHERE%s %s=%s', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left'), | |
- $curElement['left']+1); | |
- if (DB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getPath() | |
- | |
- /** | |
- * gets the path from the element with the given id down | |
- * to the root. The returned array is sorted to start at root | |
- * for simply walking through and retreiving the path | |
- * | |
- * @access public | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element for which the path shall be | |
- * returned | |
- * @return mixed either the data of the requested elements | |
- * or an Tree_Error | |
- */ | |
- function getPath($id) | |
- { | |
- $res = $this->dbh->getAll($this->_getPathQuery($id)); | |
- if (DB::isError($res)) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResults($res); | |
- } | |
- | |
- // }}} | |
- // {{{ _getPathQuery() | |
- | |
- function _getPathQuery($id) | |
- { | |
- // subqueries would be cool :-) | |
- $curElement = $this->getElement($id); | |
- $query = sprintf('SELECT * FROM %s '. | |
- 'WHERE %s %s<=%s AND %s>=%s '. | |
- 'ORDER BY %s', | |
- // set the FROM %s | |
- $this->table, | |
- // set the additional where add on | |
- $this->_getWhereAddOn(), | |
- // render 'left<=curLeft' | |
- $this->_getColName('left'),$curElement['left'], | |
- // render right>=curRight' | |
- $this->_getColName('right'),$curElement['right'], | |
- // set the order column | |
- $this->_getColName('left')); | |
- return $query; | |
- } | |
- | |
- // }}} | |
- // {{{ getLevel() | |
- | |
- function getLevel($id) | |
- { | |
- $query = $this->_getPathQuery($id); | |
- // i know this is not really beautiful ... | |
- $query = preg_replace('/^select \* /i','SELECT COUNT(*) ',$query); | |
- if (DB::isError($res = $this->dbh->getOne($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $res-1; | |
- } | |
- | |
- // }}} | |
- // {{{ getLeft() | |
- | |
- /** | |
- * gets the element to the left, the left visit | |
- * | |
- * @access public | |
- * @version 2002/03/07 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed either the data of the requested element | |
- * or an Tree_Error | |
- */ | |
- function getLeft($id) | |
- { | |
- $element = $this->getElement($id); | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- | |
- $query = sprintf('SELECT * FROM %s WHERE%s (%s=%s OR %s=%s)', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('right'),$element['left']-1, | |
- $this->_getColName('left'),$element['left']-1); | |
- if (DB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getRight() | |
- | |
- /** | |
- * gets the element to the right, the right visit | |
- * | |
- * @access public | |
- * @version 2002/03/07 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed either the data of the requested element | |
- * or an Tree_Error | |
- */ | |
- function getRight($id) | |
- { | |
- $element = $this->getElement($id); | |
- if (Tree::isError($element)) { | |
- return $element; | |
- } | |
- $query = sprintf('SELECT * FROM %s WHERE%s (%s=%s OR %s=%s)', | |
- $this->table, | |
- $this->_getWhereAddOn(), | |
- $this->_getColName('left'),$element['right']+1, | |
- $this->_getColName('right'),$element['right']+1); | |
- if (DB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getParent() | |
- | |
- /** | |
- * get the parent of the element with the given id | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed the array with the data of the parent element | |
- * or false, if there is no parent, if the element is | |
- * the root or an Tree_Error | |
- */ | |
- function getParent($id) | |
- { | |
- $query = sprintf('SELECT | |
- p.* | |
- FROM | |
- %s p,%s e | |
- WHERE | |
- %s e.%s=p.%s | |
- AND | |
- e.%s=%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'p'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $this->_getColName('id'), | |
- $id); | |
- if (DB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getChildren() | |
- | |
- /** | |
- * get the children of the given element or if the parameter is an array. | |
- * It gets the children of all the elements given by their ids | |
- * in the array. | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param mixed (1) int the id of one element | |
- * (2) array an array of ids for which | |
- * the children will be returned | |
- * @param integer the children of how many levels shall be returned | |
- * @return mixed the array with the data of all children | |
- * or false, if there are none | |
- */ | |
- function getChildren($ids, $levels = 1) | |
- { | |
- $res = array(); | |
- for ($i = 1; $i < $levels + 1; $i++) { | |
- // if $ids is an array implode the values | |
- $getIds = is_array($ids) ? implode(',',$ids) : $ids; | |
- | |
- $query = sprintf('SELECT | |
- c.* | |
- FROM | |
- %s c,%s e | |
- WHERE | |
- %s e.%s=c.%s | |
- AND | |
- e.%s IN (%s) '. | |
- 'ORDER BY | |
- c.%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'c'), | |
- $this->_getColName('id'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $getIds, | |
- // order by left, so we have it in the order | |
- // as it is in the tree if no 'order'-option | |
- // is given | |
- $this->getOption('order')? | |
- $this->getOption('order') | |
- : $this->_getColName('left') | |
- ); | |
- if (DB::isError($_res = $this->dbh->getAll($query))) { | |
- return $this->_throwError($_res->getMessage(), __LINE__); | |
- } | |
- | |
- // Column names are now unmapped | |
- $_res = $this->_prepareResults($_res); | |
- | |
- // we use the id as the index, to make the use easier esp. | |
- // for multiple return-values | |
- $tempRes = array(); | |
- foreach ($_res as $aRes) { | |
- $tempRes[$aRes['id']] = $aRes; | |
- } | |
- $_res = $tempRes; | |
- | |
- if ($levels>1) { | |
- $ids = array(); | |
- foreach($_res as $aRes) { | |
- $ids[] = $aRes[$this->_getColName('id')]; | |
- } | |
- } | |
- $res = array_merge($res,$_res); | |
- | |
- // quit the for-loop if there are no children in the current level | |
- if (!sizeof($ids)) { | |
- break; | |
- } | |
- } | |
- return $res; | |
- } | |
- | |
- // }}} | |
- // {{{ getNext() | |
- | |
- /** | |
- * get the next element on the same level | |
- * if there is none return false | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed the array with the data of the next element | |
- * or false, if there is no next | |
- * or Tree_Error | |
- */ | |
- function getNext($id) | |
- { | |
- $query = sprintf('SELECT | |
- n.* | |
- FROM | |
- %s n,%s e | |
- WHERE | |
- %s e.%s=n.%s-1 | |
- AND | |
- e.%s=n.%s | |
- AND | |
- e.%s=%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'n'), | |
- $this->_getColName('right'), | |
- $this->_getColName('left'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $id); | |
- if (DB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return !$res ? false : $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ getPrevious() | |
- | |
- /** | |
- * get the previous element on the same level | |
- * if there is none return false | |
- * | |
- * @access public | |
- * @version 2002/04/15 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element | |
- * @return mixed the array with the data of the previous element | |
- * or false, if there is no previous | |
- * or a Tree_Error | |
- */ | |
- function getPrevious($id) | |
- { | |
- $query = sprintf('SELECT | |
- p.* | |
- FROM | |
- %s p,%s e | |
- WHERE | |
- %s e.%s=p.%s+1 | |
- AND | |
- e.%s=p.%s | |
- AND | |
- e.%s=%s', | |
- $this->table,$this->table, | |
- $this->_getWhereAddOn(' AND ', 'p'), | |
- $this->_getColName('left'), | |
- $this->_getColName('right'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('parentId'), | |
- $this->_getColName('id'), | |
- $id); | |
- if (DB::isError($res = $this->dbh->getRow($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- return !$res ? false : $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ isChildOf() | |
- | |
- /** | |
- * returns if $childId is a child of $id | |
- * | |
- * @abstract | |
- * @version 2002/04/29 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param int id of the element | |
- * @param int id of the element to check if it is a child | |
- * @return boolean true if it is a child | |
- */ | |
- function isChildOf($id, $childId) | |
- { | |
- // check simply if the left and right of the child are within the | |
- // left and right of the parent, if so it definitly is a child :-) | |
- $parent = $this->getElement($id); | |
- $child = $this->getElement($childId); | |
- | |
- if ($parent['left'] < $child['left'] | |
- && $parent['right'] > $child['right']) { | |
- return true; | |
- } | |
- return false; | |
- } | |
- | |
- // }}} | |
- // {{{ getDepth() | |
- | |
- /** | |
- * return the maximum depth of the tree | |
- * | |
- * @version 2003/02/25 | |
- * @access public | |
- * @author "Denis Joloudov" <[email protected]>, Wolfram Kriesing <[email protected]> | |
- * @return integer the depth of the tree | |
- */ | |
- function getDepth() | |
- { | |
- // FIXXXME TODO!!! | |
- $query = sprintf('SELECT COUNT(*) FROM %s p, %s e '. | |
- 'WHERE %s (e.%s BETWEEN p.%s AND p.%s) AND '. | |
- '(e.%s BETWEEN p.%s AND p.%s)', | |
- $this-> table,$this->table, | |
- // first line in where | |
- $this->_getWhereAddOn(' AND ','p'), | |
- $this->_getColName('left'),$this->_getColName('left'), | |
- $this->_getColName('right'), | |
- // second where line | |
- $this->_getColName('right'),$this->_getColName('left'), | |
- $this->_getColName('right') | |
- ); | |
- if (DB::isError($res = $this->dbh->getOne($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- if (!$res) { | |
- return false; | |
- } | |
- return $this->_prepareResult($res); | |
- } | |
- | |
- // }}} | |
- // {{{ hasChildren() | |
- | |
- /** | |
- * Tells if the node with the given ID has children. | |
- * | |
- * @version 2003/03/04 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of a node | |
- * @return boolean if the node with the given id has children | |
- */ | |
- function hasChildren($id) | |
- { | |
- $element = $this->getElement($id); | |
- // if the diff between left and right>1 then there are children | |
- return ($element['right'] - $element['left']) > 1; | |
- } | |
- | |
- // }}} | |
- // {{{ getIdByPath() | |
- | |
- /** | |
- * return the id of the element which is referenced by $path | |
- * this is useful for xml-structures, like: getIdByPath('/root/sub1/sub2') | |
- * this requires the structure to use each name uniquely | |
- * if this is not given it will return the first proper path found | |
- * i.e. there should only be one path /x/y/z | |
- * experimental: the name can be non unique if same names are in different levels | |
- * | |
- * @version 2003/05/11 | |
- * @access public | |
- * @author Pierre-Alain Joye <[email protected]> | |
- * @param string $path the path to search for | |
- * @param integer $startId the id where to start the search | |
- * @param string $nodeName the name of the key that contains | |
- * the node name | |
- * @param string $seperator the path seperator | |
- * @return integer the id of the searched element | |
- */ | |
- function getIdByPath($path, $startId = 0, $nodeName = 'name', $separator = '/') | |
- // should this method be called getElementIdByPath ???? | |
- // Yes, with an optional private paramater to get the whole node | |
- // in preference to only the id? | |
- { | |
- if ($separator == '') { | |
- return $this->_throwError( | |
- 'getIdByPath: Empty separator not allowed', __LINE__); | |
- } | |
- if ($path == $separator) { | |
- $root = $this->getRoot(); | |
- if (Tree::isError($root)) { | |
- return $root; | |
- } | |
- return $root['id']; | |
- } | |
- if (!($colname=$this->_getColName($nodeName))) { | |
- return $this->_throwError( | |
- 'getIdByPath: Invalid node name', __LINE__); | |
- } | |
- if ($startId != 0) { | |
- // If the start node has no child, returns false | |
- // hasChildren calls getElement. Not very good right | |
- // now. See the TODO | |
- $startElem = $this->getElement($startId); | |
- if (!is_array($startElem) || Tree::isError($startElem)) { | |
- return $startElem; | |
- } | |
- // No child? return | |
- if (!is_array($startElem)) { | |
- return null; | |
- } | |
- $rangeStart = $startElem['left']; | |
- $rangeEnd = $startElem['right']; | |
- // Not clean, we should call hasChildren, but I do not | |
- // want to call getELement again :). See TODO | |
- $startHasChild = ($rangeEnd-$rangeStart)>1?true:false; | |
- $cwd = '/'.$this->getPathAsString($startId); | |
- } else { | |
- $cwd = '/'; | |
- $startHasChild = false; | |
- } | |
- $t = $this->_preparePath($path, $cwd, $separator); | |
- if (Tree::isError($t)) { | |
- return $t; | |
- } | |
- list($elems, $sublevels) = $t; | |
- $cntElems = sizeof($elems); | |
- $where = ''; | |
- | |
- $query = 'SELECT ' | |
- .$this->_getColName('id') | |
- .' FROM ' | |
- .$this->table | |
- . ' WHERE ' | |
- .$colname; | |
- if ($cntElems == 1) { | |
- $query .= "='".$elems[0]."'"; | |
- } else { | |
- $query .= "='".$elems[$cntElems-1]."'"; | |
- } | |
- if ($startHasChild) { | |
- $where .= ' AND ('. | |
- $this->_getColName('left').'>'.$rangeStart. | |
- ' AND '. | |
- $this->_getColName('right').'<'.$rangeEnd.')'; | |
- } | |
- $res = $this->dbh->getOne($query); | |
- if (DB::isError($res)) { | |
- return $this->_throwError($res->getMessage(), | |
- __LINE__); | |
- } | |
- return ($res ? (int)$res : false); | |
- } | |
- | |
- // }}} | |
- | |
- // | |
- // PRIVATE METHODS | |
- // | |
- | |
- // {{{ _getWhereAddOn() | |
- /** | |
- * | |
- * | |
- * @access private | |
- * @version 2002/04/20 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param string the current where clause | |
- * @return string the where clause we want to add to a query | |
- */ | |
- function _getWhereAddOn($addAfter = ' AND ', $tableName = '') | |
- { | |
- if ($where = $this->getOption('whereAddOn')) { | |
- return ' '.($tableName ? $tableName.'.' : '')." $where$addAfter "; | |
- } | |
- return ''; | |
- } | |
- | |
- // }}} | |
- // {{{ getFirstRoot() | |
- | |
- // for compatibility to Memory methods | |
- function getFirstRoot() | |
- { | |
- return $this->getRoot(); | |
- } | |
- | |
- // }}} | |
- // {{{ getNode() | |
- | |
- /** | |
- * gets the tree under the given element in one array, sorted | |
- * so you can go through the elements from begin to end and list them | |
- * as they are in the tree, where every child (until the deepest) is retreived | |
- * | |
- * @see &_getNode() | |
- * @access public | |
- * @version 2001/12/17 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer $startId the id where to start walking | |
- * @param integer $depth this number says how deep into | |
- * the structure the elements shall | |
- * be retreived | |
- * @return array sorted as listed in the tree | |
- */ | |
- function &getNode($startId = 0, $depth = 0) | |
- { | |
-//FIXXXME use getChildren() | |
- if ($startId) { | |
- $startNode = $this->getElement($startId); | |
- if (Tree::isError($startNode)) { | |
- return $startNode; | |
- } | |
- | |
- } else { | |
- } | |
- } | |
-} | |
- | |
-/* | |
- * Local Variables: | |
- * mode: php | |
- * tab-width: 4 | |
- * c-basic-offset: 4 | |
- * End: | |
- */ | |
\ No newline at end of file | |
Index: Tree/Dynamic/SQLnested.php | |
=================================================================== | |
--- Tree/Dynamic/SQLnested.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Dynamic/SQLnested.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,1317 @@ | |
+<?php | |
+/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
+// +----------------------------------------------------------------------+ | |
+// | PHP Version 4 | | |
+// +----------------------------------------------------------------------+ | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
+// +----------------------------------------------------------------------+ | |
+// | This source file is subject to version 3.0 of the PHP license, | | |
+// | that is bundled with this package in the file LICENSE, and is | | |
+// | available at through the world-wide-web at | | |
+// | http://www.php.net/license/3_0.txt. | | |
+// | If you did not receive a copy of the PHP license and are unable to | | |
+// | obtain it through the world-wide-web, please send a note to | | |
+// | [email protected] so we can mail you a copy immediately. | | |
+// +----------------------------------------------------------------------+ | |
+// | Authors: | | |
+// +----------------------------------------------------------------------+ | |
+// | |
+// $Id$ | |
+ | |
+require_once 'Tree/Tree.php'; | |
+ | |
+/** | |
+* This class implements methods to work on a tree saved using the nested | |
+* tree model. | |
+* explaination: http://research.calacademy.org/taf/proceedings/ballew/index.htm | |
+* | |
+* @access public | |
+* @package Tree | |
+*/ | |
+class Tree_Dynamic_SQLnested extends Tree | |
+{ | |
+ // {{{ __construct() | |
+ | |
+ // the defined methods here are proposals for the implementation, | |
+ // they are named the same, as the methods in the "Memory" branch. | |
+ // If possible it would be cool to keep the same naming. And | |
+ // if the same parameters would be possible too then it would be | |
+ // even better, so one could easily change from any kind | |
+ // of tree-implementation to another, without changing the source | |
+ // code, only the setupXXX would need to be changed | |
+ /** | |
+ * | |
+ * | |
+ * @access public | |
+ * @version 2002/03/02 | |
+ * @param string the DSN for the DB connection | |
+ * @return void | |
+ */ | |
+ function __construct($config) | |
+ { | |
+ $this->Tree_Dynamic_SQLnested($config); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ Tree_Dynamic_DBnested() | |
+ | |
+ /** | |
+ * | |
+ * | |
+ * @access public | |
+ * @version 2002/03/02 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param string the DSN for the DB connection | |
+ * @return void | |
+ */ | |
+ function Tree_Dynamic_SQLnested($config) | |
+ { | |
+ $this->conf = Tree::arrayMergeClobber($this->conf, $config['options']); | |
+ $this->init($config); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ add() | |
+ | |
+ /** | |
+ * add a new element to the tree | |
+ * there are three ways to use this method | |
+ * Method 1: | |
+ * Give only the $parent_id and the $newValues will be inserted | |
+ * as the first child of this parent | |
+ * <code> | |
+ * // insert a new element under the parent with the ID=7 | |
+ * $tree->add(array('name'=>'new element name'), 7); | |
+ * </code> | |
+ * | |
+ * Method 2: | |
+ * Give the $prevId ($parent_id will be dismissed) and the new element | |
+ * will be inserted in the tree after the element with the ID=$prevId | |
+ * the parent_id is not necessary because the prevId defines exactly where | |
+ * the new element has to be place in the tree, and the parent is | |
+ * the same as for the element with the ID=$prevId | |
+ * <code> | |
+ * // insert a new element after the element with the ID=5 | |
+ * $tree->add(array('name'=>'new'), 0, 5); | |
+ * </code> | |
+ * | |
+ * Method 3: | |
+ * neither $parent_id nor prevId is given, then the root element will be | |
+ * inserted. This requires that programmer is responsible to confirm this. | |
+ * This method does not yet check if there is already a root element saved! | |
+ * | |
+ * @access public | |
+ * @param array $newValues this array contains the values that shall | |
+ * be inserted in the db-table | |
+ * @param integer $parent_id the id of the element which shall be | |
+ * the parent of the new element | |
+ * @param integer $prevId the id of the element which shall preceed | |
+ * the one to be inserted use either | |
+ * 'parent_id' or 'prevId'. | |
+ * @return integer the ID of the element that had been inserted | |
+ */ | |
+ function add($newValues, $parent_id = 0, $prevId = 0) | |
+ { | |
+ $left = $this->_getColName('left'); | |
+ $right = $this->_getColName('right'); | |
+ $prevVisited = 0; | |
+ | |
+ // check the DB-table if the columns which are given as keys | |
+ // in the array $newValues do really exist, if not remove them | |
+ // from the array | |
+ // FIXXME do the above described | |
+ // if no parent and no prevId is given the root shall be added | |
+ if ($parent_id || $prevId) { | |
+ if ($prevId) { | |
+ $element = $this->getElement($prevId); | |
+ if (Tree::isError($element)) { | |
+ return $element; | |
+ } | |
+ // we also need the parent id of the element to write it in the db | |
+ $parent_id = $element['parent_id']; | |
+ } else { | |
+ $element = $this->getElement($parent_id); | |
+ } | |
+ $newValues['parent_id'] = $parent_id; | |
+ | |
+ if (Tree::isError($element)) { | |
+ return $element; | |
+ } | |
+ | |
+ // get the "visited"-value where to add the new element behind | |
+ // if $prevId is given, we need to use the right-value | |
+ // if only the $parent_id is given we need to use the left-value | |
+ // look at it graphically, that made me understand it :-) | |
+ // See: | |
+ // http://research.calacademy.org/taf/proceedings/ballew/sld034.htm | |
+ $prevVisited = $prevId ? $element['right'] : $element['left']; | |
+ | |
+ // FIXXME start transaction here | |
+ if (Tree::isError($err = $this->_add($prevVisited, 1))) { | |
+ // FIXXME rollback | |
+ //$this->_storage->rollback(); | |
+ return $err; | |
+ } | |
+ } | |
+ | |
+ // inserting _one_ new element in the tree | |
+ $newData = array(); | |
+ // quote the values, as needed for the insert | |
+ foreach ($newValues as $key => $value) { | |
+ $type = $this->conf['fields'][$key]['type']; | |
+ $newData[$this->_getColName($key)] = $this->_storage->quote($value, $type); | |
+ } | |
+ | |
+ // set the proper right and left values | |
+ $newData[$left] = $prevVisited + 1; | |
+ $newData[$right] = $prevVisited + 2; | |
+ | |
+ // use sequences to create a new id in the db-table | |
+ $nextId = $this->_storage->nextId($this->conf['table']); | |
+ $query = sprintf('INSERT INTO %s (%s, %s) VALUES (%s, %s)', | |
+ $this->conf['table'], | |
+ $this->_getColName('id'), | |
+ implode(',', array_keys($newData)) , | |
+ $this->_storage->quote($nextId, 'integer'), | |
+ implode(',', $newData) | |
+ ); | |
+ $res = $this->_storage->query($query); | |
+ if (PEAR::isError($res)) { | |
+ // rollback | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ // commit here | |
+ | |
+ return $nextId; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ _add() | |
+ | |
+ /** | |
+ * this method only updates the left/right values of all the | |
+ * elements that are affected by the insertion | |
+ * be sure to set the parent_id of the element(s) you insert | |
+ * | |
+ * @param int this parameter is not the ID!!! | |
+ * it is the previous visit number, that means | |
+ * if you are inserting a child, you need to use the left-value | |
+ * of the parent | |
+ * if you are inserting a "next" element, on the same level | |
+ * you need to give the right value !! | |
+ * @param int the number of elements you plan to insert | |
+ * @return mixed either true on success or a Tree_Error on failure | |
+ */ | |
+ function _add($prevVisited, $numberOfElements = 1) | |
+ { | |
+ $left = $this->_getColName('left'); | |
+ $right = $this->_getColName('right'); | |
+ | |
+ // update the elements which will be affected by the new insert | |
+ $query = sprintf('UPDATE %s SET %s = %s + %s WHERE%s %s > %s', | |
+ $this->conf['table'], | |
+ $left, | |
+ $left, | |
+ $numberOfElements * 2, | |
+ $this->_getWhereAddOn(), | |
+ $left, | |
+ $prevVisited); | |
+ if (PEAR::isError($res = $this->_storage->query($query))) { | |
+ // FIXXME rollback | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ $query = sprintf('UPDATE %s SET %s = %s + %s WHERE%s %s > %s', | |
+ $this->conf['table'], | |
+ $right, $right, | |
+ $numberOfElements * 2, | |
+ $this->_getWhereAddOn(), | |
+ $right, | |
+ $prevVisited); | |
+ $res = $this->_storage->query($query); | |
+ if (PEAR::isError($res)) { | |
+ // FIXXME rollback | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ return true; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ remove() | |
+ | |
+ /** | |
+ * remove a tree element | |
+ * this automatically remove all children and their children | |
+ * if a node shall be removed that has children | |
+ * | |
+ * @access public | |
+ * @param integer $id the id of the element to be removed | |
+ * @return boolean returns either true or throws an error | |
+ */ | |
+ function remove($id) | |
+ { | |
+ $element = $this->getElement($id); | |
+ if (Tree::isError($element)) { | |
+ return $element; | |
+ } | |
+ | |
+ // FIXXME start transaction | |
+ //$this->_storage->autoCommit(false); | |
+ $query = sprintf('DELETE FROM %s WHERE%s %s BETWEEN %s AND %s', | |
+ $this->conf['table'], | |
+ $this->_getWhereAddOn(), | |
+ $this->_getColName('left'), | |
+ $element['left'], $element['right']); | |
+ $res = $this->_storage->query($query); | |
+ if (PEAR::isError($res)) { | |
+ // FIXXME rollback | |
+ //$this->_storage->rollback(); | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ if (Tree::isError($err = $this->_remove($element))) { | |
+ // FIXXME rollback | |
+ //$this->_storage->rollback(); | |
+ return $err; | |
+ } | |
+ return true; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ _remove() | |
+ | |
+ /** | |
+ * removes a tree element, but only updates the left/right values | |
+ * to make it seem as if the given element would not exist anymore | |
+ * it doesnt remove the row(s) in the db itself! | |
+ * | |
+ * @see getElement() | |
+ * @access private | |
+ * @param array the entire element returned by "getElement" | |
+ * @return boolean returns either true or throws an error | |
+ */ | |
+ function _remove($element) | |
+ { | |
+ $delta = $element['right'] - $element['left'] + 1; | |
+ $left = $this->_getColName('left'); | |
+ $right = $this->_getColName('right'); | |
+ | |
+ // update the elements which will be affected by the remove | |
+ $query = sprintf("UPDATE | |
+ %s | |
+ SET | |
+ %s = %s - $delta, | |
+ %s = %s - $delta | |
+ WHERE%s %s > %s", | |
+ $this->conf['table'], | |
+ $left, $left, | |
+ $right, $right, | |
+ $this->_getWhereAddOn(), | |
+ $left, $element['left']); | |
+ $res = $this->_storage->query($query); | |
+ if (PEAR::isError($res)) { | |
+ // the rollback shall be done by the method calling this one | |
+ // since it is only private we can do that | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ $query = sprintf("UPDATE | |
+ %s | |
+ SET %s = %s - $delta | |
+ WHERE | |
+ %s %s < %s | |
+ AND | |
+ %s > %s", | |
+ $this->conf['table'], | |
+ $right, $right, | |
+ $this->_getWhereAddOn(), | |
+ $left, $element['left'], | |
+ $right, $element['right']); | |
+ $res = $this->_storage->query($query); | |
+ if (PEAR::isError($res)) { | |
+ // the rollback shall be done by the method calling this one | |
+ // since it is only private | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ // FIXXME commit: | |
+ // should that not also be done in the method calling this one? | |
+ // like when an error occurs? | |
+ //$this->_storage->commit(); | |
+ return true; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ move() | |
+ | |
+ /** | |
+ * move an entry under a given parent or behind a given entry. | |
+ * If a newPrevId is given the newparent_id is dismissed! | |
+ * call it either like this: | |
+ * $tree->move(x, y) | |
+ * to move the element (or entire tree) with the id x | |
+ * under the element with the id y | |
+ * or | |
+ * $tree->move(x, 0, y); // ommit the second parameter by setting | |
+ * it to 0 | |
+ * to move the element (or entire tree) with the id x | |
+ * behind the element with the id y | |
+ * or | |
+ * $tree->move(array(x1,x2,x3), ... | |
+ * the first parameter can also be an array of elements that shall | |
+ * be moved. the second and third para can be as described above. | |
+ * | |
+ * If you are using the Memory_DBnested then this method would be invain, | |
+ * since Memory.php already does the looping through multiple elements. | |
+ * But if Dynamic_DBnested is used we need to do the looping here | |
+ * | |
+ * @version 2002/06/08 | |
+ * @access public | |
+ * @param integer the id(s) of the element(s) that shall be moved | |
+ * @param integer the id of the element which will be the new parent | |
+ * @param integer if prevId is given the element with the id idToMove | |
+ * shall be moved _behind_ the element with id=prevId | |
+ * if it is 0 it will be put at the beginning | |
+ * @return mixed true for success, Tree_Error on failure | |
+ */ | |
+ function move($idsToMove, $newparent_id, $newPrevId = 0) | |
+ { | |
+ settype($idsToMove, 'array'); | |
+ $errors = array(); | |
+ foreach ($idsToMove as $idToMove) { | |
+ $ret = $this->_move($idToMove, $newparent_id, $newPrevId); | |
+ if (Tree::isError($ret)) { | |
+ $errors[] = $ret; | |
+ } | |
+ } | |
+ // FIXXME the error in a nicer way, or even better | |
+ // let the throwError method do it!!! | |
+ if (count($errors)) { | |
+ return Tree::raiseError(TREE_ERROR_UNKOWN_ERROR, null, null, serialize($errors)); | |
+ } | |
+ return true; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ _move() | |
+ | |
+ /** | |
+ * this method moves one tree element | |
+ * | |
+ * @see move() | |
+ * @version 2002/04/29 | |
+ * @access public | |
+ * @param integer the id of the element that shall be moved | |
+ * @param integer the id of the element which will be the new parent | |
+ * @param integer if prevId is given the element with the id idToMove | |
+ * shall be moved _behind_ the element with id=prevId | |
+ * if it is 0 it will be put at the beginning | |
+ * @return mixed true for success, Tree_Error on failure | |
+ */ | |
+ function _move($idToMove, $newparent_id, $newPrevId = 0) | |
+ { | |
+ // do some integrity checks first | |
+ if ($newPrevId) { | |
+ // dont let people move an element behind itself, tell it | |
+ // succeeded, since it already is there :-) | |
+ if ($newPrevId == $idToMove) { | |
+ return true; | |
+ } | |
+ if (Tree::isError($newPrevious = $this->getElement($newPrevId))) { | |
+ return $newPrevious; | |
+ } | |
+ $newparent_id = $newPrevious['parent_id']; | |
+ } else { | |
+ if ($newparent_id == 0) { | |
+ return Tree::raiseError(TREE_ERROR_UNKOWN_ERROR, null, null, 'no parent id given'); | |
+ } | |
+ // if the element shall be moved under one of its children | |
+ // return false | |
+ if ($this->isChildOf($idToMove, $newparent_id)) { | |
+ return Tree::raiseError(TREE_ERROR_UNKOWN_ERROR, null, null, | |
+ 'can not move an element under one of its children'); | |
+ } | |
+ // dont do anything to let an element be moved under itself | |
+ // which is bullshit | |
+ if ($newparent_id == $idToMove) { | |
+ return true; | |
+ } | |
+ // try to retreive the data of the parent element | |
+ if (Tree::isError($newParent = $this->getElement($newparent_id))) { | |
+ return $newParent; | |
+ } | |
+ } | |
+ // get the data of the element itself | |
+ if (Tree::isError($element = $this->getElement($idToMove))) { | |
+ return $element; | |
+ } | |
+ | |
+ $numberOfElements = ($element['right'] - $element['left'] + 1) / 2; | |
+ $prevVisited = $newPrevId ? $newPrevious['right'] : $newParent['left']; | |
+ | |
+ // FIXXME start transaction | |
+ | |
+ // add the left/right values in the new parent, to have the space | |
+ // to move the new values in | |
+ $err = $this->_add($prevVisited, $numberOfElements); | |
+ if (Tree::isError($err)) { | |
+ // FIXXME rollback | |
+ //$this->_storage->rollback(); | |
+ return $err; | |
+ } | |
+ | |
+ // update the parent_id of the element with $idToMove | |
+ $err = $this->update($idToMove, array('parent_id' => $newparent_id)); | |
+ if (Tree::isError($err)) { | |
+ // FIXXME rollback | |
+ //$this->_storage->rollback(); | |
+ return $err; | |
+ } | |
+ | |
+ // update the lefts and rights of those elements that shall be moved | |
+ | |
+ // first get the offset we need to add to the left/right values | |
+ // if $newPrevId is given we need to get the right value, | |
+ // otherwise the left since the left/right has changed | |
+ // because we already updated it up there. We need to get them again. | |
+ // We have to do that anyway, to have the proper new left/right values | |
+ if ($newPrevId) { | |
+ if (Tree::isError($temp = $this->getElement($newPrevId))) { | |
+ // FIXXME rollback | |
+ //$this->_storage->rollback(); | |
+ return $temp; | |
+ } | |
+ $calcWith = $temp['right']; | |
+ } else { | |
+ if (Tree::isError($temp = $this->getElement($newparent_id))) { | |
+ // FIXXME rollback | |
+ //$this->_storage->rollback(); | |
+ return $temp; | |
+ } | |
+ $calcWith = $temp['left']; | |
+ } | |
+ | |
+ // get the element that shall be moved again, since the left and | |
+ // right might have changed by the add-call | |
+ if (Tree::isError($element = $this->getElement($idToMove))) { | |
+ return $element; | |
+ } | |
+ // calc the offset that the element to move has | |
+ // to the spot where it should go | |
+ // correct the offset by one, since it needs to go inbetween! | |
+ $offset = $calcWith - $element['left'] + 1; | |
+ | |
+ $left = $this->_getColName('left'); | |
+ $right = $this->_getColName('right'); | |
+ $query = sprintf("UPDATE | |
+ %s | |
+ SET | |
+ %s = %s + $offset, | |
+ %s = %s + $offset | |
+ WHERE | |
+ %s %s > %s | |
+ AND | |
+ %s < %s", | |
+ $this->conf['table'], | |
+ $right, $right, | |
+ $left, $left, | |
+ $this->_getWhereAddOn(), | |
+ $left, $element['left'] - 1, | |
+ $right, $element['right'] + 1); | |
+ if (PEAR::isError($res = $this->_storage->query($query))) { | |
+ // FIXXME rollback | |
+ //$this->_storage->rollback(); | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ // remove the part of the tree where the element(s) was/were before | |
+ if (Tree::isError($err = $this->_remove($element))) { | |
+ // FIXXME rollback | |
+ //$this->_storage->rollback(); | |
+ return $err; | |
+ } | |
+ // FIXXME commit all changes | |
+ //$this->_storage->commit(); | |
+ | |
+ return true; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ update() | |
+ | |
+ /** | |
+ * update the tree element given by $id with the values in $newValues | |
+ * | |
+ * @access public | |
+ * @param int the id of the element to update | |
+ * @param array the new values, the index is the col name | |
+ * @return mixed either true or an Tree_Error | |
+ */ | |
+ function update($id, $newValues) | |
+ { | |
+ // just to be sure nothing gets screwed up :-) | |
+ unset($newValues[$this->_getColName('left')]); | |
+ unset($newValues[$this->_getColName('right')]); | |
+ unset($newValues[$this->_getColName('parent_id')]); | |
+ | |
+ // updating _one_ element in the tree | |
+ $values = array(); | |
+ foreach ($newValues as $key => $value) { | |
+ $type = $this->conf['fields'][$key]['type']; | |
+ $values[] = $this->_getColName($key) . ' = ' . $this->_storage->quote($value, $type); | |
+ } | |
+ $query = sprintf('UPDATE %s SET %s WHERE%s %s = %s', | |
+ $this->conf['table'], | |
+ implode(',', $values), | |
+ $this->_getWhereAddOn(), | |
+ $this->_getColName('id'), | |
+ $id); | |
+ $res = $this->_storage->query($query); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ return true; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ update() | |
+ | |
+ /** | |
+ * copy a subtree/node/... under a new parent or/and behind a given element | |
+ * | |
+ * | |
+ * @access public | |
+ * @param integer the ID of the node that shall be copied | |
+ * @param integer the new parent ID | |
+ * @param integer the new previous ID, if given parent ID will be omitted | |
+ * @return boolean true on success | |
+ */ | |
+ function copy($id, $parent_id = 0, $prevId = 0) | |
+ { | |
+ return Tree::raiseError(TREE_ERROR_NOT_IMPLEMENTED, null, null, | |
+ 'copy-method is not implemented yet!'); | |
+ // get element tree | |
+ // $this->addTree | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getRoot() | |
+ | |
+ /** | |
+ * get the root | |
+ * | |
+ * @access public | |
+ * @version 2002/03/02 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @return mixed either the data of the root element or an Tree_Error | |
+ */ | |
+ function getRoot() | |
+ { | |
+ $query = sprintf('SELECT * FROM %s WHERE%s %s = 1', | |
+ $this->conf['table'], | |
+ $this->_getWhereAddOn(), | |
+ $this->_getColName('left')); | |
+ $res = $this->_storage->queryRow($query, array()); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ return !$res ? false : $this->_prepareResult($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getElement() | |
+ | |
+ /** | |
+ * | |
+ * | |
+ * @access public | |
+ * @version 2002/03/02 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer the ID of the element to return | |
+ * | |
+ * @return mixed either the data of the requested element | |
+ * or an Tree_Error | |
+ */ | |
+ function getElement($id) | |
+ { | |
+ $query = sprintf('SELECT * FROM %s WHERE %s %s = %s', | |
+ $this->conf['table'], | |
+ $this->_getWhereAddOn(), | |
+ $this->_getColName('id'), | |
+ $id); | |
+ $res = $this->_storage->queryRow($query, array()); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ if (!$res) { | |
+ return Tree::raiseError(TREE_ERROR_UNKOWN_ERROR, null, null, "Element with id $id does not exist!"); | |
+ } | |
+ | |
+ return $this->_prepareResult($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getPath() | |
+ | |
+ /** | |
+ * gets the path from the element with the given id down | |
+ * to the root. The returned array is sorted to start at root | |
+ * for simply walking through and retreiving the path | |
+ * | |
+ * @access public | |
+ * @param integer the ID of the element for which the path shall be returned | |
+ * @return mixed either the data of the requested elements | |
+ * or an Tree_Error | |
+ */ | |
+ function getPath($id) | |
+ { | |
+ $query = $this->_getPathQuery($id); | |
+ if (PEAR::isError($query)) { | |
+ /// FIXME return real tree error | |
+ return false; | |
+ } | |
+ | |
+ $res = $this->_storage->queryAll($query, array(), false, false); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ return $this->_prepareResults($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ _getPathQuery() | |
+ | |
+ function _getPathQuery($id) | |
+ { | |
+ // subqueries would be cool :-) | |
+ $curElement = $this->getElement($id); | |
+ if (PEAR::isError($curElement)) { | |
+ /// FIXME return real tree error | |
+ return false; | |
+ } | |
+ | |
+ $left = $this->_getColName('left'); | |
+ $query = sprintf('SELECT * FROM %s '. | |
+ 'WHERE %s %s <= %s AND %s >= %s '. | |
+ 'ORDER BY %s', | |
+ // set the FROM %s | |
+ $this->conf['table'], | |
+ // set the additional where add on | |
+ $this->_getWhereAddOn(), | |
+ // render 'left<=curLeft' | |
+ $left, $curElement['left'], | |
+ // render right>=curRight' | |
+ $this->_getColName('right'), $curElement['right'], | |
+ // set the order column | |
+ $left); | |
+ return $query; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getLevel() | |
+ | |
+ function getLevel($id) | |
+ { | |
+ $query = $this->_getPathQuery($id); | |
+ // i know this is not really beautiful ... | |
+ $id = $this->_getColName('id'); | |
+ $replace = "SELECT COUNT($id) "; | |
+ $query = preg_replace('/^select \* /i', $replace, $query); | |
+ $res = $this->_storage->queryOne($query, 'integer'); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ return $res - 1; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getLeft() | |
+ | |
+ /** | |
+ * gets the element to the left, the left visit | |
+ * | |
+ * @access public | |
+ * @version 2002/03/07 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer the ID of the element | |
+ * @return mixed either the data of the requested element | |
+ * or an Tree_Error | |
+ */ | |
+ function getLeft($id) | |
+ { | |
+ $element = $this->getElement($id); | |
+ if (Tree::isError($element)) { | |
+ return $element; | |
+ } | |
+ | |
+ $query = sprintf('SELECT * FROM %s WHERE%s (%s = %s OR %s = %s)', | |
+ $this->conf['table'], | |
+ $this->_getWhereAddOn(), | |
+ $this->_getColName('right'), $element['left'] - 1, | |
+ $this->_getColName('left'), $element['left'] - 1); | |
+ $res = $this->_storage->queryRow($query, array()); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ return $this->_prepareResult($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getRight() | |
+ | |
+ /** | |
+ * gets the element to the right, the right visit | |
+ * | |
+ * @access public | |
+ * @version 2002/03/07 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer the ID of the element | |
+ * @return mixed either the data of the requested element | |
+ * or an Tree_Error | |
+ */ | |
+ function getRight($id) | |
+ { | |
+ $element = $this->getElement($id); | |
+ if (Tree::isError($element)) { | |
+ return $element; | |
+ } | |
+ | |
+ $query = sprintf('SELECT * FROM %s WHERE%s (%s = %s OR %s = %s)', | |
+ $this->conf['table'], | |
+ $this->_getWhereAddOn(), | |
+ $this->_getColName('left'), $element['right'] + 1, | |
+ $this->_getColName('right'), $element['right'] + 1); | |
+ $res = $this->_storage->queryRow($query, array()); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ return $this->_prepareResult($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getParent() | |
+ | |
+ /** | |
+ * get the parent of the element with the given id | |
+ * | |
+ * @access public | |
+ * @version 2002/04/15 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer the ID of the element | |
+ * @return mixed the array with the data of the parent element | |
+ * or false, if there is no parent, if the element is | |
+ * the root or an Tree_Error | |
+ */ | |
+ function getParent($id) | |
+ { | |
+ $idName = $this->_getColName('id'); | |
+ $query = sprintf('SELECT | |
+ p.* | |
+ FROM | |
+ %s p,%s e | |
+ WHERE | |
+ %s e.%s = p.%s | |
+ AND | |
+ e.%s = %s', | |
+ $this->conf['table'], $this->conf['table'], | |
+ $this->_getWhereAddOn(' AND ', 'p'), | |
+ $this->_getColName('parent_id'), | |
+ $idName, | |
+ $idName, | |
+ $id); | |
+ $res = $this->_storage->queryRow($query, array()); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ return $this->_prepareResult($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getChild() | |
+ | |
+ /** | |
+ * | |
+ * | |
+ * @access public | |
+ * @version 2002/03/02 | |
+ * @param integer the ID of the element for which the children | |
+ * shall be returned | |
+ * @return mixed either the data of the requested element or an Tree_Error | |
+ */ | |
+ function _getChild($id) | |
+ { | |
+ // subqueries would be cool :-) | |
+ $curElement = $this->getElement($id); | |
+ if (Tree::isError($curElement)) { | |
+ return $curElement; | |
+ } | |
+ | |
+ $query = sprintf('SELECT * FROM %s WHERE%s %s = %s', | |
+ $this->conf['table'], | |
+ $this->_getWhereAddOn(), | |
+ $this->_getColName('left'), | |
+ $curElement['left'] + 1); | |
+ $res = $this->_storage->queryRow($query, array()); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ return $this->_prepareResult($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getChildren() | |
+ | |
+ /** | |
+ * get the children of the given element or if the parameter is an array. | |
+ * It gets the children of all the elements given by their ids | |
+ * in the array. | |
+ * | |
+ * @access public | |
+ * @version 2002/04/15 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param mixed (1) int the id of one element | |
+ * (2) array an array of ids for which | |
+ * the children will be returned | |
+ * @param boolean if only the first child should be returned (only used when one id is passed) | |
+ * @param integer the children of how many levels shall be returned | |
+ * @return mixed the array with the data of all children | |
+ * or false, if there are none | |
+ */ | |
+ function getChildren($ids, $oneChild = false, $levels = 1) | |
+ { | |
+ if ($oneChild) { | |
+ $res = $this->_getChild($ids); | |
+ return $res; | |
+ } | |
+ | |
+ $id = $this->_getColName('id'); | |
+ $parent = $this->_getColName('parent_id'); | |
+ $left = $this->_getColName('left'); | |
+ $where = $this->_getWhereAddOn(' AND ', 'c'); | |
+ $orderBy = $this->getOption('order') ? $this->getOption('order') : $left; | |
+ | |
+ $res = array(); | |
+ for ($i = 1; $i < $levels + 1; $i++) { | |
+ // if $ids is an array implode the values | |
+ $getIds = is_array($ids) ? implode(',', $ids) : $ids; | |
+ | |
+ $query = sprintf('SELECT | |
+ c.* | |
+ FROM | |
+ %s c,%s e | |
+ WHERE | |
+ %s e.%s = c.%s | |
+ AND | |
+ e.%s IN (%s) '. | |
+ 'ORDER BY | |
+ c.%s', | |
+ $this->conf['table'], $this->conf['table'], | |
+ $where, | |
+ $id, | |
+ $parent, | |
+ $id, | |
+ $getIds, | |
+ // order by left, so we have it in the order | |
+ // as it is in the tree if no 'order'-option | |
+ // is given | |
+ $orderBy | |
+ ); | |
+ $_res = $this->_storage->queryAll($query, array(), false, false); | |
+ if (PEAR::isError($_res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $_res->getMessage()); | |
+ } | |
+ | |
+ // Column names are now unmapped | |
+ $_res = $this->_prepareResults($_res); | |
+ | |
+ if ($levels > 1) { | |
+ $ids = array(); | |
+ } | |
+ | |
+ // we use the id as the index, to make the use easier esp. | |
+ // for multiple return-values | |
+ $tempRes = array(); | |
+ foreach ($_res as $aRes) { | |
+ ///FIXME This part might be replace'able with key'ed array return | |
+ $tempRes[$aRes['id']] = $aRes; | |
+ // If there are more levels requested then get the id for the next level | |
+ if ($levels > 1) { | |
+ $ids[] = $aRes[$id]; | |
+ } | |
+ } | |
+ | |
+ $res = array_merge($res, $tempRes); | |
+ | |
+ // quit the for-loop if there are no children in the current level | |
+ if (!count($ids)) { | |
+ break; | |
+ } | |
+ } | |
+ | |
+ return $res; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ nextSibling() | |
+ | |
+ /** | |
+ * get the next element on the same level | |
+ * if there is none return false | |
+ * | |
+ * @access public | |
+ * @version 2002/04/15 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer the ID of the element | |
+ * @return mixed the array with the data of the next element | |
+ * or false, if there is no next | |
+ * or Tree_Error | |
+ */ | |
+ function nextSibling($id) | |
+ { | |
+ $parent = $this->_getColName('parent_id'); | |
+ $query = sprintf('SELECT | |
+ n.* | |
+ FROM | |
+ %s n, %s e | |
+ WHERE | |
+ %s e.%s = n.%s - 1 | |
+ AND | |
+ e.%s = n.%s | |
+ AND | |
+ e.%s = %s', | |
+ $this->conf['table'], $this->conf['table'], | |
+ $this->_getWhereAddOn(' AND ', 'n'), | |
+ $this->_getColName('right'), | |
+ $this->_getColName('left'), | |
+ $parent, | |
+ $parent, | |
+ $this->_getColName('id'), | |
+ $id); | |
+ $res = $this->_storage->queryRow($query, array()); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ return !$res ? false : $this->_prepareResult($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ previousSibling() | |
+ | |
+ /** | |
+ * get the previous element on the same level | |
+ * if there is none return false | |
+ * | |
+ * @access public | |
+ * @version 2002/04/15 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer the ID of the element | |
+ * @return mixed the array with the data of the previous element | |
+ * or false, if there is no previous | |
+ * or a Tree_Error | |
+ */ | |
+ function previousSibling($id) | |
+ { | |
+ $parent = $this->_getColName('parent_id'); | |
+ $query = sprintf('SELECT | |
+ p.* | |
+ FROM | |
+ %s p, %s e | |
+ WHERE | |
+ %s e.%s = p.%s + 1 | |
+ AND | |
+ e.%s = p.%s | |
+ AND | |
+ e.%s = %s', | |
+ $this->conf['table'], $this->conf['table'], | |
+ $this->_getWhereAddOn(' AND ', 'p'), | |
+ $this->_getColName('left'), | |
+ $this->_getColName('right'), | |
+ $parent, | |
+ $parent, | |
+ $this->_getColName('id'), | |
+ $id); | |
+ $res = $this->_storage->queryRow($query, array()); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ return !$res ? false : $this->_prepareResult($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ isChildOf() | |
+ | |
+ /** | |
+ * returns if $childId is a child of $id | |
+ * | |
+ * @abstract | |
+ * @version 2002/04/29 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param int id of the element | |
+ * @param int id of the element to check if it is a child | |
+ * @return boolean true if it is a child | |
+ */ | |
+ function isChildOf($id, $childId) | |
+ { | |
+ // check simply if the left and right of the child are within the | |
+ // left and right of the parent, if so it definitly is a child :-) | |
+ $parent = $this->getElement($id); | |
+ if (PEAR::isError($parent)) { | |
+ /// FIXME return real tree error | |
+ return false; | |
+ } | |
+ | |
+ $child = $this->getElement($childId); | |
+ if (PEAR::isError($child)) { | |
+ /// FIXME return real tree error | |
+ return false; | |
+ } | |
+ | |
+ if ($parent['left'] < $child['left'] | |
+ && $parent['right'] > $child['right']) | |
+ { | |
+ return true; | |
+ } | |
+ | |
+ return false; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getDepth() | |
+ | |
+ /** | |
+ * return the maximum depth of the tree | |
+ * | |
+ * @version 2003/02/25 | |
+ * @access public | |
+ * @author "Denis Joloudov" <[email protected]>, Wolfram Kriesing <[email protected]> | |
+ * @return integer the depth of the tree | |
+ */ | |
+ function getDepth() | |
+ { | |
+ $left = $this->_getColName('left'); | |
+ $right = $this->_getColName('right'); | |
+ // FIXXXME TODO!!! | |
+ $query = sprintf('SELECT COUNT(*) FROM %s p, %s e '. | |
+ 'WHERE %s (e.%s BETWEEN p.%s AND p.%s) AND '. | |
+ '(e.%s BETWEEN p.%s AND p.%s)', | |
+ $this->conf['table'], $this->conf['table'], | |
+ // first line in where | |
+ $this->_getWhereAddOn(' AND ','p'), | |
+ $left, $left, $right, | |
+ // second where line | |
+ $right, $left, $right | |
+ ); | |
+ $res = $this->_storage->queryOne($query, 'integer'); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ | |
+ if (!$res) { | |
+ return false; | |
+ } | |
+ | |
+ return $this->_prepareResult($res); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ hasChildren() | |
+ | |
+ /** | |
+ * Tells if the node with the given ID has children. | |
+ * | |
+ * @version 2003/03/04 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer the ID of a node | |
+ * @return boolean if the node with the given id has children | |
+ */ | |
+ function hasChildren($id) | |
+ { | |
+ $element = $this->getElement($id); | |
+ if (PEAR::isError($element)) { | |
+ return false; | |
+ } | |
+ // if the diff between left and right > 1 then there are children | |
+ return ($element['right'] - $element['left']) > 1; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getIdByPath() | |
+ | |
+ /** | |
+ * return the id of the element which is referenced by $path | |
+ * this is useful for xml-structures, like: getIdByPath('/root/sub1/sub2') | |
+ * this requires the structure to use each name uniquely | |
+ * if this is not given it will return the first proper path found | |
+ * i.e. there should only be one path /x/y/z | |
+ * experimental: the name can be non unique if same names are in different levels | |
+ * | |
+ * @version 2003/05/11 | |
+ * @access public | |
+ * @author Pierre-Alain Joye <[email protected]> | |
+ * @param string $path the path to search for | |
+ * @param integer $startId the id where to start the search | |
+ * @param string $nodeName the name of the key that contains | |
+ * the node name | |
+ * @param string $seperator the path seperator | |
+ * @return integer the id of the searched element | |
+ */ | |
+ function getIdByPath($path, $startId = 0, $nodeName = 'name', $separator = '/') | |
+ // should this method be called getElementIdByPath ???? | |
+ // Yes, with an optional private paramater to get the whole node | |
+ // in preference to only the id? | |
+ { | |
+ if ($separator == '') { | |
+ return Tree::raiseError(TREE_ERROR_UNKOWN_ERROR, null, null, | |
+ 'getIdByPath: Empty separator not allowed'); | |
+ } | |
+ | |
+ if ($path == $separator) { | |
+ if (Tree::isError($root = $this->getRoot())) { | |
+ return $root; | |
+ } | |
+ return $root['id']; | |
+ } | |
+ | |
+ if (!($colname = $this->_getColName($nodeName))) { | |
+ return Tree::raiseError(TREE_ERROR_UNKOWN_ERROR, null, null, | |
+ 'getIdByPath: Invalid node name'); | |
+ } | |
+ | |
+ if ($startId != 0) { | |
+ // If the start node has no child, returns false | |
+ // hasChildren calls getElement. Not very good right | |
+ // now. See the TODO | |
+ $startElem = $this->getElement($startId); | |
+ if (Tree::isError($startElem)) { | |
+ return $startElem; | |
+ } | |
+ | |
+ // No child? return | |
+ if (!is_array($startElem)) { | |
+ return null; | |
+ } | |
+ | |
+ $rangeStart = $startElem['left']; | |
+ $rangeEnd = $startElem['right']; | |
+ // Not clean, we should call hasChildren, but I do not | |
+ // want to call getELement again :). See TODO | |
+ $startHasChild = ($rangeEnd - $rangeStart) > 1 ? true : false; | |
+ $cwd = '/' . $this->getPathAsString($startId); | |
+ } else { | |
+ $cwd = '/'; | |
+ $startHasChild = false; | |
+ } | |
+ | |
+ $t = $this->_preparePath($path, $cwd, $separator); | |
+ if (Tree::isError($t)) { | |
+ return $t; | |
+ } | |
+ | |
+ list($elems, $sublevels) = $t; | |
+ $cntElems = count($elems); | |
+ | |
+ $query = ' | |
+ SELECT ' | |
+ . $this->_getColName('id') . | |
+ ' FROM ' | |
+ . $this->conf['table'] . | |
+ ' WHERE ' | |
+ . $colname; | |
+ | |
+ $element = $cntElems == 1 ? $elems[0] : $elems[$cntElems - 1]; | |
+ $query .= ' = ' . $this->_storage->quote($element, 'text'); | |
+ | |
+ if ($startHasChild) { | |
+ $query .= ' AND ('. | |
+ $this->_getColName('left').' > '.$rangeStart. | |
+ ' AND '. | |
+ $this->_getColName('right').' < '.$rangeEnd.')'; | |
+ } | |
+ | |
+ $res = $this->_storage->queryOne($query, 'integer'); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ return $res ? (int)$res : false; | |
+ } | |
+ | |
+ // }}} | |
+ | |
+ // {{{ _getWhereAddOn() | |
+ /** | |
+ * | |
+ * | |
+ * @access private | |
+ * @version 2002/04/20 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param string the current where clause | |
+ * @return string the where clause we want to add to a query | |
+ */ | |
+ function _getWhereAddOn($addAfter = ' AND ', $tableName = '') | |
+ { | |
+ if (!empty($this->conf['whereAddOn'])) { | |
+ return ' ' . ($tableName ? $tableName . '.' : '') . $this->conf['whereAddOn'] . $addAfter; | |
+ } | |
+ return ''; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getFirstRoot() | |
+ | |
+ // for compatibility to Memory methods | |
+ function getFirstRoot() | |
+ { | |
+ return $this->getRoot(); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getBranch() | |
+ | |
+ /** | |
+ * gets the tree under the given element in one array, sorted | |
+ * so you can go through the elements from begin to end and list them | |
+ * as they are in the tree, where every child (until the deepest) is retreived | |
+ * | |
+ * @see &_getBranch() | |
+ * @access public | |
+ * @version 2001/12/17 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer $startId the id where to start walking | |
+ * @param integer $depth this number says how deep into | |
+ * the structure the elements shall | |
+ * be retreived | |
+ * @return array sorted as listed in the tree | |
+ */ | |
+ function &getBranch($startId = 0, $depth = 0) | |
+ { | |
+//FIXXXME use getChildren() | |
+ if ($startId) { | |
+ $startNode = $this->getElement($startId); | |
+ if (Tree::isError($startNode)) { | |
+ return $startNode; | |
+ } | |
+ | |
+ } else { | |
+ } | |
+ } | |
+} | |
+ | |
+/* | |
+ * Local Variables: | |
+ * mode: php | |
+ * tab-width: 4 | |
+ * c-basic-offset: 4 | |
+ * End: | |
+ */ | |
+?> | |
Property changes on: Tree/Dynamic/SQLnested.php | |
___________________________________________________________________ | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Index: Tree/Storage/SQL.php | |
=================================================================== | |
--- Tree/Storage/SQL.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Storage/SQL.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,77 @@ | |
+<?php | |
+ | |
+/** | |
+ * Require parent class definition. | |
+ */ | |
+require_once 'Tree/Storage.php'; | |
+ | |
+class Tree_Storage_SQL extends Tree_Storage { | |
+ /** | |
+ * dsn that was connected to | |
+ * | |
+ * @var object | |
+ * @access private | |
+ */ | |
+ var $dsn = null; | |
+ | |
+ /** | |
+ * Database connection object. | |
+ * | |
+ * @var object | |
+ * @access private | |
+ */ | |
+ var $dbc = null; | |
+ | |
+ /** | |
+ * Table prefix | |
+ * Prefix for all db tables the container has. | |
+ * | |
+ * @var string | |
+ * @access public | |
+ */ | |
+ var $prefix = 'liveuser_'; | |
+ | |
+ /** | |
+ * Table configuration | |
+ * | |
+ * @var array | |
+ * @access public | |
+ */ | |
+ var $tables = array(); | |
+ | |
+ /** | |
+ * All fields with their types | |
+ * | |
+ * @var array | |
+ * @access public | |
+ */ | |
+ var $fields = array(); | |
+ | |
+ /** | |
+ * All fields with their alias | |
+ * | |
+ * @var array | |
+ * @access public | |
+ */ | |
+ var $alias = array(); | |
+ | |
+ function insert($table, $data) | |
+ { | |
+ | |
+ } | |
+ | |
+ function update($table, $data, $filters) | |
+ { | |
+ | |
+ } | |
+ | |
+ function remove($table, $filters) | |
+ { | |
+ | |
+ } | |
+ | |
+ function select() | |
+ { | |
+ | |
+ } | |
+} | |
\ No newline at end of file | |
Property changes on: Tree/Storage/SQL.php | |
___________________________________________________________________ | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Index: Tree/Storage/MDB.php | |
=================================================================== | |
--- Tree/Storage/MDB.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Storage/MDB.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,348 @@ | |
+<?php | |
+// LiveUser: A framework for authentication and authorization in PHP applications | |
+// Copyright (C) 2002-2003 Markus Wolff | |
+// | |
+// This library is free software; you can redistribute it and/or | |
+// modify it under the terms of the GNU Lesser General Public | |
+// License as published by the Free Software Foundation; either | |
+// version 2.1 of the License, or (at your option) any later version. | |
+// | |
+// This library is distributed in the hope that it will be useful, | |
+// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+// Lesser General Public License for more details. | |
+// | |
+// You should have received a copy of the GNU Lesser General Public | |
+// License along with this library; if not, write to the Free Software | |
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
+ | |
+/** | |
+ * MDB_Complex container for permission handling | |
+ * | |
+ * @package LiveUser | |
+ * @category authentication | |
+ */ | |
+ | |
+/** | |
+ * Require parent class definition. | |
+ */ | |
+require_once 'Tree/Storage/SQL.php'; | |
+require_once 'MDB.php'; | |
+ | |
+/** | |
+ * This is a PEAR::MDB backend driver for the LiveUser class. | |
+ * A PEAR::MDB connection object can be passed to the constructor to reuse an | |
+ * existing connection. Alternatively, a DSN can be passed to open a new one. | |
+ * | |
+ * Requirements: | |
+ * - File "Liveuser.php" (contains the parent class "LiveUser") | |
+ * - Array of connection options or a PEAR::MDB connection object must be | |
+ * passed to the constructor. | |
+ * Example: array('dsn' => 'mysql://user:pass@host/db_name') | |
+ * OR | |
+ * &$conn (PEAR::MDB connection object) | |
+ * | |
+ * @author Lukas Smith <[email protected]> | |
+ * @author Bjoern Kraus <[email protected]> | |
+ * @version $Id$ | |
+ * @package LiveUser | |
+ * @category authentication | |
+ */ | |
+class Tree_Storage_MDB extends Tree_Storage_SQL | |
+{ | |
+ /** | |
+ * Initializes database storage container. | |
+ * Connects to database or uses existing database connection. | |
+ * | |
+ * @param array &$storageConf Storage Configuration | |
+ * @return boolean false on failure and true on success | |
+ * | |
+ * @access public | |
+ * @uses Tree_Storage_SQL::init | |
+ */ | |
+ function init(&$storageConf) | |
+ { | |
+ if (isset($storageConf['connection']) && | |
+ MDB::isConnection($storageConf['connection']) | |
+ ) { | |
+ $this->dbc = &$storageConf['connection']; | |
+ } elseif (isset($storageConf['dsn'])) { | |
+ $this->dsn = $storageConf['dsn']; | |
+ $function = null; | |
+ if (isset($storageConf['function'])) { | |
+ $function = $storageConf['function']; | |
+ } | |
+ $options = null; | |
+ if (isset($storageConf['options'])) { | |
+ $options = $storageConf['options']; | |
+ } | |
+ $options['optimize'] = 'portability'; | |
+ if ($function == 'singleton') { | |
+ $this->dbc =& MDB::singleton($storageConf['dsn'], $options); | |
+ } else { | |
+ $this->dbc =& MDB::connect($storageConf['dsn'], $options); | |
+ } | |
+ if (PEAR::isError($this->dbc)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, 'could not create connection: '.$this->dbc->getMessage()); | |
+ } | |
+ } | |
+ return true; | |
+ } | |
+ | |
+ /** | |
+ * Convert a text value into a DBMS specific format that is suitable to | |
+ * compose query statements. | |
+ * | |
+ * @param string $value text string value that is intended to be converted. | |
+ * @param string $type type to which the value should be converted to | |
+ * @return stringtext string that represents the given argument value in | |
+ * a DBMS specific format. | |
+ * | |
+ * @access public | |
+ * @uses MDB::getValue | |
+ */ | |
+ function quote($value, $type) | |
+ { | |
+ return $this->dbc->getValue($type, $value); | |
+ } | |
+ | |
+ /** | |
+ * Apply a type to all values of an array and return as a comma | |
+ * seperated string useful for generating IN statements | |
+ * | |
+ * @param array $array data array | |
+ * @param string $type determines type of the field | |
+ * | |
+ * @return string comma seperated values | |
+ * | |
+ * @access public | |
+ * @uses MDB::getValue | |
+ */ | |
+ function implodeArray($array, $type) | |
+ { | |
+ if (!is_array($array) || empty($array)) { | |
+ return 'NULL'; | |
+ } | |
+ foreach ($array as $value) { | |
+ $return[] = $this->dbc->getValue($type, $value); | |
+ } | |
+ return implode(', ', $return); | |
+ } | |
+ | |
+ /** | |
+ * Sets the range of the next query | |
+ * | |
+ * @param string $limit number of rows to select | |
+ * @param string $offset first row to select | |
+ * | |
+ * @return | |
+ * | |
+ * @access public | |
+ * @uses MDB::setSelectedRowRange | |
+ */ | |
+ function setLimit($limit, $offset) | |
+ { | |
+ if ($limit || $offset) { | |
+ return $this->dbc->setSelectedRowRange($offset, $limit); | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * Execute query | |
+ * | |
+ * @param string $query query | |
+ * @return boolean | integer | |
+ * | |
+ * @access public | |
+ * @uses MDB::query MDB::affectedRows | |
+ */ | |
+ function query($query) | |
+ { | |
+ $result = $this->dbc->query($query); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $this->dbc->affectedRows(); | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch the value from the first column of | |
+ * the first row of the result set and then frees | |
+ * the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param string $type argument that specifies the expected | |
+ * datatype of the result set field, so that an eventual conversion | |
+ * may be performed. The default datatype is text, meaning that no | |
+ * conversion is performed | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses MDB::queryOne | |
+ */ | |
+ function queryOne($query, $type) | |
+ { | |
+ if (is_array($type)) { | |
+ $type = reset($type); | |
+ } | |
+ $result = $this->dbc->queryOne($query, $type); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch the values from the first | |
+ * row of the result set into an array and then frees | |
+ * the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param array $type array argument that specifies a list of | |
+ * expected datatypes of the result set columns, so that the eventual | |
+ * conversions may be performed. The default list of datatypes is | |
+ * empty, meaning that no conversion is performed. | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses MDB::queryRow | |
+ */ | |
+ function queryRow($query, $type) | |
+ { | |
+ $result = $this->dbc->queryRow($query, $type, MDB_FETCHMODE_ASSOC); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch the value from the first column of | |
+ * each row of the result set into an array and then frees the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param string $type argument that specifies the expected | |
+ * datatype of the result set field, so that an eventual conversion | |
+ * may be performed. The default datatype is text, meaning that no | |
+ * conversion is performed | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses MDB::queryCol | |
+ */ | |
+ function queryCol($query, $type) | |
+ { | |
+ if (is_array($type)) { | |
+ $type = reset($type); | |
+ } | |
+ $result = $this->dbc->queryCol($query, $type); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch all the rows of the result set into | |
+ * a two dimensional array and then frees the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param array $types array argument that specifies a list of | |
+ * expected datatypes of the result set columns, so that the eventual | |
+ * conversions may be performed. The default list of datatypes is | |
+ * empty, meaning that no conversion is performed. | |
+ * @param boolean $rekey if set to true, the $all will have the first | |
+ * column as its first dimension | |
+ * @param boolean $group if set to true and $rekey is set to true, then | |
+ * all values with the same first column will be wrapped in an array | |
+ * @param boolean $group if set to true and $rekey is set to true, then | |
+ * all values with the same first column will be wrapped in an array | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses MDB::queryAll | |
+ */ | |
+ function queryAll($query, $types, $rekey, $group) | |
+ { | |
+ $result = $this->dbc->queryAll($query, $types, MDB_FETCHMODE_ASSOC, $rekey, false, $group); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * returns the next free id of a sequence | |
+ * | |
+ * @param string $seqname name of the sequence | |
+ * @param boolean $ondemand when true the seqence is | |
+ * automatic created, if it not exists | |
+ * @return boolean | integer | |
+ * | |
+ * @access public | |
+ * @uses MDB::nextId | |
+ */ | |
+ function nextId($seqname, $ondemand = true) | |
+ { | |
+ $result = $this->dbc->nextId($seqname, $ondemand); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * returns the next free id of a sequence if the RDBMS | |
+ * does not support auto increment | |
+ * | |
+ * @param string $table name of the table into which a new row was inserted | |
+ * @param boolean $ondemand when true the seqence is | |
+ * automatic created, if it not exists | |
+ * @return boolean | integer | |
+ * | |
+ * @access public | |
+ * @uses MDB::nextId | |
+ */ | |
+ function getBeforeId($table, $ondemand = true) | |
+ { | |
+ $result = $this->dbc->nextId($table, $ondemand); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * returns the autoincrement ID if supported or $id | |
+ * | |
+ * getAfterId isn't implemented in MDB so we return the $id that | |
+ * was passed by the user | |
+ * | |
+ * @param string $id value as returned by getBeforeId() | |
+ * @param string $table name of the table into which a new row was inserted | |
+ * @return integer returns the id that the users passed via params | |
+ * | |
+ * @access public | |
+ */ | |
+ function getAfterId($id, $table) | |
+ { | |
+ return $id; | |
+ } | |
+ | |
+ /** | |
+ * | |
+ * @return mixed false on error or the result | |
+ * | |
+ * @access public | |
+ * @uses MDB::disconnect | |
+ */ | |
+ function disconnect() | |
+ { | |
+ $result = $this->dbc->disconnect(); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+} | |
+?> | |
Property changes on: Tree/Storage/MDB.php | |
___________________________________________________________________ | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Index: Tree/Storage/MDB2.php | |
=================================================================== | |
--- Tree/Storage/MDB2.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Storage/MDB2.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,347 @@ | |
+<?php | |
+// LiveUser: A framework for authentication and authorization in PHP applications | |
+// Copyright (C) 2002-2003 Markus Wolff | |
+// | |
+// This library is free software; you can redistribute it and/or | |
+// modify it under the terms of the GNU Lesser General Public | |
+// License as published by the Free Software Foundation; either | |
+// version 2.1 of the License, or (at your option) any later version. | |
+// | |
+// This library is distributed in the hope that it will be useful, | |
+// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+// Lesser General Public License for more details. | |
+// | |
+// You should have received a copy of the GNU Lesser General Public | |
+// License along with this library; if not, write to the Free Software | |
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
+ | |
+/** | |
+ * MDB2_Complex container for permission handling | |
+ * | |
+ * @package LiveUser | |
+ * @category authentication | |
+ */ | |
+ | |
+/** | |
+ * Require parent class definition. | |
+ */ | |
+require_once 'Tree/Storage/SQL.php'; | |
+require_once 'MDB2.php'; | |
+ | |
+/** | |
+ * This is a PEAR::MDB2 backend driver for the LiveUser class. | |
+ * A PEAR::MDB2 connection object can be passed to the constructor to reuse an | |
+ * existing connection. Alternatively, a DSN can be passed to open a new one. | |
+ * | |
+ * Requirements: | |
+ * - File "Liveuser.php" (contains the parent class "LiveUser") | |
+ * - Array of connection options or a PEAR::MDB2 connection object must be | |
+ * passed to the constructor. | |
+ * Example: array('dsn' => 'mysql://user:pass@host/db_name') | |
+ * OR | |
+ * &$conn (PEAR::MDB2 connection object) | |
+ * | |
+ * @author Lukas Smith <[email protected]> | |
+ * @author Bjoern Kraus <[email protected]> | |
+ * @version $Id$ | |
+ * @package LiveUser | |
+ * @category authentication | |
+ */ | |
+class Tree_Storage_MDB2 extends Tree_Storage_SQL | |
+{ | |
+ var $force_seq = true; | |
+ | |
+ /** | |
+ * Initializes database storage container. | |
+ * Connects to database or uses existing database connection. | |
+ * | |
+ * @param array &$storageConf Storage Configuration | |
+ * @return boolean false on failure and true on success | |
+ * | |
+ * @access public | |
+ * @uses Tree_Storage_SQL::init | |
+ */ | |
+ function init(&$storageConf) | |
+ { | |
+ if (isset($storageConf['connection']) && | |
+ MDB2::isConnection($storageConf['connection']) | |
+ ) { | |
+ $this->dbc = &$storageConf['connection']; | |
+ } elseif (isset($storageConf['dsn'])) { | |
+ $this->dsn = $storageConf['dsn']; | |
+ $function = null; | |
+ if (isset($storageConf['function'])) { | |
+ $function = $storageConf['function']; | |
+ } | |
+ $options = null; | |
+ if (isset($storageConf['options'])) { | |
+ $options = $storageConf['options']; | |
+ } | |
+ $options['portability'] = MDB2_PORTABILITY_ALL; | |
+ if ($function == 'singleton') { | |
+ $this->dbc =& MDB2::singleton($storageConf['dsn'], $options); | |
+ } else { | |
+ $this->dbc =& MDB2::connect($storageConf['dsn'], $options); | |
+ } | |
+ if (PEAR::isError($this->dbc)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, 'could not create connection: '.$this->dbc->getMessage()); | |
+ } | |
+ } | |
+ return true; | |
+ } | |
+ | |
+ /** | |
+ * Convert a text value into a DBMS specific format that is suitable to | |
+ * compose query statements. | |
+ * | |
+ * @param string $value text string value that is intended to be converted. | |
+ * @param string $type type to which the value should be converted to | |
+ * @return stringtext string that represents the given argument value in | |
+ * a DBMS specific format. | |
+ * | |
+ * @access public | |
+ * @uses MDB2::quote | |
+ */ | |
+ function quote($value, $type) | |
+ { | |
+ return $this->dbc->quote($value, $type); | |
+ } | |
+ | |
+ /** | |
+ * Apply a type to all values of an array and return as a comma | |
+ * seperated string useful for generating IN statements | |
+ * | |
+ * @param array $array data array | |
+ * @param string $type determines type of the field | |
+ * | |
+ * @return string comma seperated values | |
+ * | |
+ * @access public | |
+ * @uses MDB2::implodeArray | |
+ */ | |
+ function implodeArray($array, $type) | |
+ { | |
+ $this->dbc->loadModule('datatype'); | |
+ return $this->dbc->datatype->implodeArray($array, $type); | |
+ } | |
+ | |
+ /** | |
+ * Sets the range of the next query | |
+ * | |
+ * @param string $limit number of rows to select | |
+ * @param string $offset first row to select | |
+ * @return | |
+ * | |
+ * @access public | |
+ * @uses MDB2::setLimit | |
+ */ | |
+ function setLimit($limit, $offset) | |
+ { | |
+ if ($limit || $offset) { | |
+ return $this->dbc->setLimit($limit, $offset); | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * Execute query | |
+ * | |
+ * @param string $query query | |
+ * @return boolean | integer | |
+ * | |
+ * @access public | |
+ * @uses MDB::query | |
+ */ | |
+ function query($query) | |
+ { | |
+ $result = $this->dbc->query($query); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch the value from the first column of | |
+ * the first row of the result set and then frees | |
+ * the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param string $type argument that specifies the expected | |
+ * datatype of the result set field, so that an eventual conversion | |
+ * may be performed. The default datatype is text, meaning that no | |
+ * conversion is performed | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses MDB2::queryOne | |
+ */ | |
+ function queryOne($query, $type) | |
+ { | |
+ $result = $this->dbc->queryOne($query, $type); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch the values from the first | |
+ * row of the result set into an array and then frees | |
+ * the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param array $type array argument that specifies a list of | |
+ * expected datatypes of the result set columns, so that the eventual | |
+ * conversions may be performed. The default list of datatypes is | |
+ * empty, meaning that no conversion is performed. | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses MDB2::queryRow | |
+ */ | |
+ function queryRow($query, $type) | |
+ { | |
+ $result = $this->dbc->queryRow($query, $type, MDB2_FETCHMODE_ASSOC); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch the value from the first column of | |
+ * each row of the result set into an array and then frees the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param string $type argument that specifies the expected | |
+ * datatype of the result set field, so that an eventual conversion | |
+ * may be performed. The default datatype is text, meaning that no | |
+ * conversion is performed | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses MDB2::queryCol | |
+ */ | |
+ function queryCol($query, $type) | |
+ { | |
+ $result = $this->dbc->queryCol($query, $type); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch all the rows of the result set into | |
+ * a two dimensional array and then frees the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param array $types array argument that specifies a list of | |
+ * expected datatypes of the result set columns, so that the eventual | |
+ * conversions may be performed. The default list of datatypes is | |
+ * empty, meaning that no conversion is performed. | |
+ * @param boolean $rekey if set to true, the $all will have the first | |
+ * column as its first dimension | |
+ * @param boolean $group if set to true and $rekey is set to true, then | |
+ * all values with the same first column will be wrapped in an array | |
+ * @param boolean $group if set to true and $rekey is set to true, then | |
+ * all values with the same first column will be wrapped in an array | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses MDB2::queryAll | |
+ */ | |
+ function queryAll($query, $types, $rekey, $group) | |
+ { | |
+ $result = $this->dbc->queryAll($query, $types, MDB2_FETCHMODE_ASSOC, $rekey, false, $group); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * returns the next free id of a sequence | |
+ * | |
+ * @param string $seqname name of the sequence | |
+ * @param boolean $ondemand when true the seqence is | |
+ * automatic created, if it not exists | |
+ * @return boolean | integer | |
+ * | |
+ * @access public | |
+ * @uses MDB2::nextId | |
+ */ | |
+ function nextId($seqname, $ondemand = true) | |
+ { | |
+ $result = $this->dbc->nextId($seqname, $ondemand); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * returns the next free id of a sequence if the RDBMS | |
+ * does not support auto increment | |
+ * | |
+ * @param string $table name of the table into which a new row was inserted | |
+ * @param boolean $ondemand when true the seqence is | |
+ * automatic created, if it not exists | |
+ * @return boolean | integer | |
+ * | |
+ * @access public | |
+ * @uses MDB2::nextId MDB2::getBeforeId | |
+ */ | |
+ function getBeforeId($table, $ondemand = true) | |
+ { | |
+ if ($this->force_seq) { | |
+ $result = $this->dbc->nextId($table, $ondemand); | |
+ } else { | |
+ $result = $this->dbc->getBeforeId($table); | |
+ } | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * returns the autoincrement ID if supported or $id | |
+ * | |
+ * @param string $id value as returned by getBeforeId() | |
+ * @param string $table name of the table into which a new row was inserted | |
+ * @return boolean | integer returns the id that the users passed via params | |
+ * | |
+ * @access public | |
+ * @uses MDB2::getAfterId | |
+ */ | |
+ function getAfterId($id, $table) | |
+ { | |
+ if ($this->force_seq) { | |
+ return $id; | |
+ } | |
+ $result = $this->dbc->getAfterId($id, $table); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * | |
+ * @return mixed false on error or the result | |
+ * | |
+ * @access public | |
+ * @uses MDB2::disconnect | |
+ */ | |
+ function disconnect() | |
+ { | |
+ $result = $this->dbc->disconnect(); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+} | |
+?> | |
Property changes on: Tree/Storage/MDB2.php | |
___________________________________________________________________ | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Index: Tree/Storage/DB.php | |
=================================================================== | |
--- Tree/Storage/DB.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Storage/DB.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,334 @@ | |
+<?php | |
+// LiveUser: A framework for authentication and authorization in PHP applications | |
+// Copyright (C) 2002-2003 Markus Wolff | |
+// | |
+// This library is free software; you can redistribute it and/or | |
+// modify it under the terms of the GNU Lesser General Public | |
+// License as published by the Free Software Foundation; either | |
+// version 2.1 of the License, or (at your option) any later version. | |
+// | |
+// This library is distributed in the hope that it will be useful, | |
+// but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+// Lesser General Public License for more details. | |
+// | |
+// You should have received a copy of the GNU Lesser General Public | |
+// License along with this library; if not, write to the Free Software | |
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
+ | |
+/** | |
+ * DB_Complex container for permission handling | |
+ * | |
+ * @package LiveUser | |
+ * @category authentication | |
+ */ | |
+ | |
+/** | |
+ * Require parent class definition. | |
+ */ | |
+require_once 'Tree/Storage/SQL.php'; | |
+require_once 'DB.php'; | |
+ | |
+/** | |
+ * This is a PEAR::DB backend driver for the LiveUser class. | |
+ * A PEAR::DB connection object can be passed to the constructor to reuse an | |
+ * existing connection. Alternatively, a DSN can be passed to open a new one. | |
+ * | |
+ * Requirements: | |
+ * - File "Liveuser.php" (contains the parent class "LiveUser") | |
+ * - Array of connection options or a PEAR::DB connection object must be | |
+ * passed to the constructor. | |
+ * Example: array('dsn' => 'mysql://user:pass@host/db_name') | |
+ * OR | |
+ * &$conn (PEAR::DB connection object) | |
+ * | |
+ * @author Lukas Smith <[email protected]> | |
+ * @author Bjoern Kraus <[email protected]> | |
+ * @version $Id$ | |
+ * @package Tree | |
+ * @category Structurs | |
+ */ | |
+class Tree_Storage_DB extends Tree_Storage_SQL | |
+{ | |
+ /** | |
+ * Initializes database storage container. | |
+ * Connects to database or uses existing database connection. | |
+ * | |
+ * @param array &$storageConf Storage Configuration | |
+ * @return boolean false on failure and true on success | |
+ * | |
+ * @access public | |
+ * @uses Tree_Storage_SQL::init | |
+ */ | |
+ function init(&$storageConf) | |
+ { | |
+ if (isset($storageConf['connection']) && | |
+ DB::isConnection($storageConf['connection']) | |
+ ) { | |
+ $this->dbc = &$storageConf['connection']; | |
+ } elseif (isset($storageConf['dsn'])) { | |
+ $this->dsn = $storageConf['dsn']; | |
+ $options = null; | |
+ if (isset($storageConf['options'])) { | |
+ $options = $storageConf['options']; | |
+ } | |
+ $options['portability'] = DB_PORTABILITY_ALL; | |
+ $this->dbc =& DB::connect($storageConf['dsn'], $options); | |
+ if (PEAR::isError($this->dbc)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, 'could not create connection: '.$this->dbc->getMessage()); | |
+ } | |
+ } | |
+ return true; | |
+ } | |
+ | |
+ /** | |
+ * Convert a text value into a DBMS specific format that is suitable to | |
+ * compose query statements. | |
+ * | |
+ * @param string $value text string value that is intended to be converted. | |
+ * @param string $type type to which the value should be converted to | |
+ * @return stringtext string that represents the given argument value in | |
+ * a DBMS specific format. | |
+ * | |
+ * @access public | |
+ * @uses DB::quoteSmart | |
+ */ | |
+ function quote($value, $type) | |
+ { | |
+ return $this->dbc->quoteSmart($value); | |
+ } | |
+ | |
+ /** | |
+ * | |
+ * @param array $array | |
+ * @param string $type | |
+ * @return string | |
+ * | |
+ * @access public | |
+ * @uses DB::quoteSmart | |
+ */ | |
+ function implodeArray($array, $type) | |
+ { | |
+ if (!is_array($array) || empty($array)) { | |
+ return 'NULL'; | |
+ } | |
+ foreach ($array as $value) { | |
+ $return[] = $this->dbc->quoteSmart($value); | |
+ } | |
+ return implode(', ', $return); | |
+ } | |
+ | |
+ /** | |
+ * This function is not implemented into DB so we | |
+ * can't make use of it. | |
+ * | |
+ * @param string $limit | |
+ * @param string $offset | |
+ * @return boolean false This feature isn't supported by DB | |
+ * | |
+ * @access public | |
+ */ | |
+ function setLimit($limit, $offset) | |
+ { | |
+ if ($limit || $offset) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, 'limit is not supported by this backend'); | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * Execute query | |
+ * | |
+ * @param string $query query | |
+ * @return boolean | integer | |
+ * | |
+ * @access public | |
+ * @uses DB::query DB::affectedRows | |
+ */ | |
+ function query($query) | |
+ { | |
+ $result = $this->dbc->query($query); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $this->dbc->affectedRows(); | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch the value from the first column of | |
+ * the first row of the result set and then frees | |
+ * the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param string $type argument that specifies the expected | |
+ * datatype of the result set field, so that an eventual conversion | |
+ * may be performed. The default datatype is text, meaning that no | |
+ * conversion is performed | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses DB::getOne | |
+ */ | |
+ function queryOne($query, $type) | |
+ { | |
+ $result = $this->dbc->getOne($query); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch the values from the first | |
+ * row of the result set into an array and then frees | |
+ * the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param array $type array argument that specifies a list of | |
+ * expected datatypes of the result set columns, so that the eventual | |
+ * conversions may be performed. The default list of datatypes is | |
+ * empty, meaning that no conversion is performed. | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses DB::getRow | |
+ */ | |
+ function queryRow($query, $type) | |
+ { | |
+ $result = $this->dbc->getRow($query, null, DB_FETCHMODE_ASSOC); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch the value from the first column of | |
+ * each row of the result set into an array and then frees the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param string $type argument that specifies the expected | |
+ * datatype of the result set field, so that an eventual conversion | |
+ * may be performed. The default datatype is text, meaning that no | |
+ * conversion is performed | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses DB::getCol | |
+ */ | |
+ function queryCol($query, $type) | |
+ { | |
+ $result = $this->dbc->getCol($query); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * Execute the specified query, fetch all the rows of the result set into | |
+ * a two dimensional array and then frees the result set. | |
+ * | |
+ * @param string $query the SELECT query statement to be executed. | |
+ * @param array $types array argument that specifies a list of | |
+ * expected datatypes of the result set columns, so that the eventual | |
+ * conversions may be performed. The default list of datatypes is | |
+ * empty, meaning that no conversion is performed. | |
+ * @param boolean $rekey if set to true, the $all will have the first | |
+ * column as its first dimension | |
+ * @param boolean $group if set to true and $rekey is set to true, then | |
+ * all values with the same first column will be wrapped in an array | |
+ * @param boolean $group if set to true and $rekey is set to true, then | |
+ * all values with the same first column will be wrapped in an array | |
+ * @return boolean | array | |
+ * | |
+ * @access public | |
+ * @uses DB::getAll DB::getAssoc | |
+ */ | |
+ function queryAll($query, $types, $rekey, $group) | |
+ { | |
+ if ($rekey) { | |
+ $result = $this->dbc->getAssoc($query, false, array(), DB_FETCHMODE_ASSOC, $group); | |
+ } else { | |
+ $result = $this->dbc->getAll($query, array(), DB_FETCHMODE_ASSOC); | |
+ } | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * returns the next free id of a sequence | |
+ * | |
+ * @param string $seqname name of the sequence | |
+ * @param boolean $ondemand when true the seqence is | |
+ * automatic created, if it not exists | |
+ * @return boolean | integer false on failure or next id for the table | |
+ * | |
+ * @access public | |
+ * @uses DB::nextId | |
+ */ | |
+ function nextId($seqname, $ondemand = true) | |
+ { | |
+ $result = $this->dbc->nextId($seqname, $ondemand); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * returns the next free id of a sequence if the RDBMS | |
+ * does not support auto increment | |
+ * | |
+ * @param string $table name of the table into which a new row was inserted | |
+ * @param boolean $ondemand when true the seqence is | |
+ * automatic created, if it not exists | |
+ * @return boolean | integer | |
+ * | |
+ * @access public | |
+ * @uses DB::nextId | |
+ */ | |
+ function getBeforeId($table, $ondemand = true) | |
+ { | |
+ $result = $this->dbc->nextId($table, $ondemand); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+ | |
+ /** | |
+ * returns the autoincrement ID if supported or $id | |
+ * | |
+ * getAfterId isn't implemented in DB so we return the $id that | |
+ * was passed by the user | |
+ * | |
+ * @param string $id value as returned by getBeforeId() | |
+ * @param string $table name of the table into which a new row was inserted | |
+ * @return integer returns the id that the users passed via params | |
+ * | |
+ * @access public | |
+ */ | |
+ function getAfterId($id, $table) | |
+ { | |
+ return $id; | |
+ } | |
+ | |
+ /** | |
+ * | |
+ * @return mixed false on error or the result | |
+ * | |
+ * @access public | |
+ * @uses DB::disconnect | |
+ */ | |
+ function disconnect() | |
+ { | |
+ $result = $this->dbc->disconnect(); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ return $result; | |
+ } | |
+} | |
+?> | |
Property changes on: Tree/Storage/DB.php | |
___________________________________________________________________ | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Index: Tree/Tree.php | |
=================================================================== | |
--- Tree/Tree.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Tree.php (.../trunk) (revision 321102) | |
@@ -3,12 +3,12 @@ | |
// +----------------------------------------------------------------------+ | |
// | PHP Version 4 | | |
// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2004 The PHP Group | | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
+// | This source file is subject to version 3.0 of the PHP license, | | |
// | that is bundled with this package in the file LICENSE, and is | | |
// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
+// | http://www.php.net/license/3_0.txt. | | |
// | If you did not receive a copy of the PHP license and are unable to | | |
// | obtain it through the world-wide-web, please send a note to | | |
// | [email protected] so we can mail you a copy immediately. | | |
@@ -19,6 +19,12 @@ | |
// $Id$ | |
/** | |
+ * Include PEAR | |
+ */ | |
+ | |
+require_once 'PEAR.php'; | |
+ | |
+/** | |
* the DB interface to the tree class | |
* | |
* @access public | |
@@ -26,11 +32,92 @@ | |
* @version 2001/06/27 | |
* @package Tree | |
*/ | |
+ | |
+define('TREE_ERROR', -1); | |
+define('TREE_ERROR_NOT_IMPLEMENTED', -2); | |
+define('TREE_ERROR_ELEMENT_NOT_FOUND', -3); | |
+define('TREE_ERROR_INVALID_NODE_NAME', -4); | |
+define('TREE_ERROR_MOVE_TO_CHILDREN', -5); | |
+define('TREE_ERROR_PARENT_ID_MISSED', -6); | |
+define('TREE_ERROR_INVALID_PARENT', -7); | |
+define('TREE_ERROR_EMPTY_PATH', -8); | |
+define('TREE_ERROR_INVALID_PATH', -9); | |
+define('TREE_ERROR_DB_ERROR', -10); | |
+define('TREE_ERROR_PATH_SEPARATOR_EMPTY', -11); | |
+define('TREE_ERROR_CANNOT_CREATE_FOLDER', -12); | |
+define('TREE_ERROR_UNKOWN_ERROR', -13); | |
+ | |
+ | |
class Tree | |
{ | |
- // {{{ setupMemory() | |
+ /** | |
+ * @var array you need to overwrite this array and give the keys/ | |
+ * that are allowed | |
+ */ | |
+ var $_forceSetOption = false; | |
/** | |
+ * 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 $conf = array( | |
+ 'whereAddOn' => '', | |
+ 'table' => '', | |
+ // since the internal names are fixed, to be portable between different | |
+ // DB tables with different column namings, we map the internal name | |
+ // to the real column name using this array here, if it stays empty | |
+ // the internal names are used, which are: | |
+ // id, left, right | |
+ 'fields' => array( | |
+ 'id' => array('type' => 'integer', 'name' => 'id'), | |
+ 'name' => array('type' => 'text', 'name' => 'name'), | |
+ // since mysql at least doesnt support 'left' ... | |
+ 'left' => array('type' => 'text', 'name' => 'l'), | |
+ // ...as a column name we set default to the first | |
+ //letter only | |
+ 'right' => array('type' => 'text', 'name' => 'r'), | |
+ // parent id | |
+ 'parent_id' => array('type' => 'integer', 'name' => 'parent') | |
+ ), | |
+ 'order' => 'id' | |
+ ); | |
+ | |
+ /** | |
+ * Storage Container | |
+ * | |
+ * @var object | |
+ */ | |
+ var $_storage = null; | |
+ | |
+ /** | |
+ * Factory | |
+ * | |
+ * @static | |
+ * @access public | |
+ * @return object | |
+ * @param string | |
+ * @param string | |
+ * @param array | |
+ */ | |
+/* function &factory($type = 'Simple', $container = 'MDB2', $options = array()) | |
+ { | |
+ $type = ucfirst(strtolower($type)); | |
+ $container = strtoupper($container); | |
+ $class = 'Tree_'. $type .'_'. $container; | |
+ require_once strtr($class, '_', '/') .'.php'; | |
+ $tree = &new $class($options); | |
+ if (Tree::isError($e = $tree->setup($options))) { | |
+ return $e; | |
+ } | |
+ return $tree; | |
+ } | |
+*/ | |
+ | |
+ /** | |
* setup an object which works on trees that are temporarily saved in | |
* memory dont use with huge trees, suggested is a maximum size of tree | |
* of 1000-5000 elements since the entire tree is read at once | |
@@ -58,19 +145,16 @@ | |
* @param mixed the dsn, or filename, etc., empty i.e. for XML | |
* if you use setupByRawData | |
*/ | |
- function &setupMemory($type, $dsn = '', $options = array()) | |
+ function &factoryMemory($config) | |
{ | |
// if anyone knows a better name it would be great to change it. | |
// since "setupMemory" kind of reflects it but i think it's not obvious | |
// if you dont know what is meant | |
include_once 'Tree/Memory.php'; | |
- $memory = &new Tree_Memory($type, $dsn, $options); | |
+ $memory = new Tree_Memory($config); | |
return $memory; | |
} | |
- // }}} | |
- // {{{ setupDynamic() | |
- | |
/** | |
* setup an object that works on trees where each element(s) are read | |
* on demand from the given data source actually this was intended to serve | |
@@ -89,19 +173,23 @@ | |
* it would be the filename | |
* @param array the options you want to set | |
*/ | |
- function &setupDynamic($type, $dsn, $options = array()) | |
+ function &factoryDynamic($config) | |
{ | |
// "dynamic" stands for retreiving a tree(chunk) dynamically when needed, | |
// better name would be great :-) | |
- include_once "Tree/Dynamic/$type.php"; | |
- $className = 'Tree_Dynamic_'.$type; | |
- $obj = & new $className($dsn, $options); | |
- return $obj; | |
+ if (in_array(strtoupper($config['storage']['name']), array('DB', 'MDB', 'MDB2'))) { | |
+ $name = 'SQL'; | |
+ } else { | |
+ $name = strtoupper($config['storage']['name']); | |
+ } | |
+ | |
+ $name .= strtolower($config['type']); | |
+ include_once "Tree/Dynamic/$name.php"; | |
+ $className = 'Tree_Dynamic_' . $name; | |
+ $dynamic = new $className($config); | |
+ return $dynamic; | |
} | |
- // }}} | |
- // {{{ setup() | |
- | |
/** | |
* this is just a wrapper around the two setup methods above | |
* some example calls: | |
@@ -145,31 +233,883 @@ | |
* for XML it would be the filename | |
* @param array the options you want to set | |
*/ | |
- function setup($type, $dsn = '', $options = array()) | |
+ function &factory($config) | |
{ | |
- $type = explode('_', $type); | |
- $method = 'setup'.$type[0]; | |
- return Tree::$method($type[1], $dsn, $options); | |
+ if (!isset($config['container'])) { | |
+ return Tree::raiseError(TREE_ERROR, null, null, 'Config option container wasn\t set.'); | |
+ } | |
+ $method = 'factory' . $config['container']; | |
+ return Tree::$method($config); | |
} | |
- // }}} | |
+ /** | |
+ * Returns an instance of a storage Container | |
+ * | |
+ * @param array configuration array to pass to the storage container | |
+ * @param string $classprefix Prefix of the class that will be used. | |
+ * @return object|false will return an instance of a Storage container | |
+ * or false upon error | |
+ * | |
+ * @author LiveUser | |
+ * @access protected | |
+ */ | |
+ function &storageFactory(&$confArray, $classprefix = 'Tree_') | |
+ { | |
+ $storageName = $classprefix . 'Storage_' . $confArray['name']; | |
+ if (!Tree::loadClass($storageName) && count($confArray) <= 1) { | |
+ $return = false; | |
+ return $return; | |
+ // if the storage container does not exist try the next one in the stack | |
+ } | |
+ | |
+ $storage = new $storageName(); | |
+ if (PEAR::isError($storage->init($confArray))) { | |
+ $return = false; | |
+ return $return; | |
+ } | |
+ | |
+ return $storage; | |
+ } | |
+ | |
+ /** | |
+ * Load the storage container | |
+ * | |
+ * @access public | |
+ * @param mixed Name of array containing the configuration. | |
+ * @return boolean true on success or false on failure | |
+ */ | |
+ function init($conf) | |
+ { | |
+ if (!isset($conf['storage'])) { | |
+ return Tree::raiseError(TREE_ERROR, null, null, 'Missing storage configuration array'); | |
+ } | |
+ | |
+ if (is_array($conf)) { | |
+ $keys = array_keys($conf); | |
+ foreach ($keys as $key) { | |
+ if (isset($this->$key)) { | |
+ $this->$key =& $conf[$key]; | |
+ } | |
+ } | |
+ } | |
+ | |
+ $this->_storage = Tree::storageFactory($conf['storage']); | |
+ if ($this->_storage === false) { | |
+ return Tree::raiseError(TREE_ERROR, null, null, 'Could not instanciate storage container'); | |
+ } | |
+ | |
+ return true; | |
+ } | |
+ | |
+ /** | |
+ * Loads a PEAR class. | |
+ * | |
+ * @param string classname to load | |
+ * @param bool if errors should be supressed from the stack | |
+ * @return bool true success or false on failure | |
+ * | |
+ * @access public | |
+ */ | |
+ function loadClass($classname, $supress_error = false) | |
+ { | |
+ if (!Tree::classExists($classname)) { | |
+ $filename = str_replace('_', '/', $classname).'.php'; | |
+ @include_once($filename); | |
+ if (!Tree::classExists($classname) && !$supress_error) { | |
+ if (!Tree::fileExists($filename)) { | |
+ $msg = 'File for the class does not exist ' . $classname; | |
+ } else { | |
+ $msg = 'Parse error in the file for class' . $classname; | |
+ } | |
+// PEAR_ErrorStack::staticPush('LiveUser', LIVEUSER_ERROR_CONFIG, | |
+// 'exception', array(), $msg); | |
+ return false; | |
+ } | |
+ } | |
+ return true; | |
+ } | |
+ | |
+ /** | |
+ * Checks if a file exists in the include path. | |
+ * | |
+ * @param string filename | |
+ * @return bool true success and false on error | |
+ * | |
+ * @access public | |
+ */ | |
+ function fileExists($filename) | |
+ { | |
+ // safe_mode does notwork with is_readable() | |
+ if (ini_get('safe_mode')) { | |
+ $fp = @fopen($file, 'r', true); | |
+ if (is_resource($fp)) { | |
+ @fclose($fp); | |
+ return true; | |
+ } | |
+ } else { | |
+ $dirs = explode(PATH_SEPARATOR, ini_get('include_path')); | |
+ foreach ($dirs as $dir) { | |
+ if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) { | |
+ return true; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * Checks if a class exists without triggering __autoload | |
+ * | |
+ * @param string classname | |
+ * @return bool true success and false on error | |
+ * | |
+ * @access public | |
+ */ | |
+ function classExists($classname) | |
+ { | |
+ if (version_compare(phpversion(), '5.0', '>=')) { | |
+ return class_exists($classname, false); | |
+ } | |
+ return class_exists($classname); | |
+ } | |
+ | |
+ /** | |
+ * Clobbers two arrays together. | |
+ * | |
+ * Function taken from the user notes of array_merge_recursive function | |
+ * and may be called statically | |
+ * | |
+ * @param array array that should be clobbered | |
+ * @param array array that should be clobbered | |
+ * @return array|false array on success and false on error | |
+ * | |
+ * @access public | |
+ * @author [email protected] | |
+ */ | |
+ function arrayMergeClobber($a1, $a2) | |
+ { | |
+ if (!is_array($a1) || !is_array($a2)) { | |
+ return false; | |
+ } | |
+ foreach ($a2 as $key => $val) { | |
+ if (is_array($val) && array_key_exists($key, $a1) && is_array($a1[$key])) { | |
+ $a1[$key] = Tree::arrayMergeClobber($a1[$key], $val); | |
+ } else { | |
+ $a1[$key] = $val; | |
+ } | |
+ } | |
+ return $a1; | |
+ } | |
+ | |
+ /** | |
+ * This method is used to communicate an error and invoke error | |
+ * callbacks etc. Basically a wrapper for PEAR::raiseError | |
+ * without the message string. | |
+ * | |
+ * @param mixed integer error code, or a PEAR error object (all | |
+ * other parameters are ignored if this parameter is | |
+ * an object | |
+ * | |
+ * @param int error mode, see PEAR_Error docs | |
+ * | |
+ * @param mixed If error mode is PEAR_ERROR_TRIGGER, this is the | |
+ * error level (E_USER_NOTICE etc). If error mode is | |
+ * PEAR_ERROR_CALLBACK, this is the callback function, | |
+ * either as a function name, or as an array of an | |
+ * object and method name. For other error modes this | |
+ * parameter is ignored | |
+ * @param string Extra debug information. Defaults to the last | |
+ * query and native error code. | |
+ * | |
+ * @return object a PEAR error object | |
+ * | |
+ * @see PEAR_Error | |
+ */ | |
+ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null) | |
+ { | |
+ $tmp = PEAR::raiseError(null, $code, $mode, $options, $userinfo, 'Tree_Error', true); | |
+ return $tmp; | |
+ } | |
+ | |
+ /** | |
+ * Return a textual error message for a MDB2 error code | |
+ * | |
+ * @param int|array $value integer error code, | |
+ null to get the current error code-message map, | |
+ or an array with a new error code-message map | |
+ * @return string error message, or false if the error code was | |
+ * not recognized | |
+ * @access public | |
+ */ | |
+ function errorMessage($value = null) | |
+ { | |
+ // make the variable static so that it only has to do the defining on the first call | |
+ static $errorMessages; | |
+ | |
+ // define the varies error messages | |
+ if (is_array($value)) { | |
+ $errorMessages = $value; | |
+ return MDB2_OK; | |
+ } elseif (!isset($errorMessages)) { | |
+ $errorMessages = array( | |
+ TREE_ERROR => 'Unkown error', | |
+ TREE_ERROR_NOT_IMPLEMENTED => 'This method is currently not implemented', | |
+ TREE_ERROR_INVALID_PATH => 'Invalid Path', | |
+ TREE_ERROR_DB_ERROR => 'Database error', | |
+ TREE_ERROR_PARENT_ID_MISSED => 'Parent ID is missing', | |
+ TREE_ERROR_MOVE_TO_CHILDREN => 'Move to children', | |
+ TREE_ERROR_ELEMENT_NOT_FOUND => 'Element not found', | |
+ TREE_ERROR_PATH_SEPARATOR_EMPTY => 'Path separator empty', | |
+ TREE_ERROR_INVALID_NODE_NAME => 'Invalid node name', | |
+ TREE_ERROR_UNKOWN_ERROR => 'Unkown error', | |
+ ); | |
+ } | |
+ | |
+ if (is_null($value)) { | |
+ return $errorMessages; | |
+ } | |
+ | |
+ // If this is an error object, then grab the corresponding error code | |
+ if (PEAR::isError($value)) { | |
+ $value = $value->getCode(); | |
+ } | |
+ | |
+ // return the textual error message corresponding to the code | |
+ return isset($errorMessages[$value]) ? $errorMessages[$value] : | |
+ $errorMessages[TREE_ERROR]; | |
+ } | |
+ | |
// {{{ isError() | |
/** | |
- * Tell whether a result code from a DB method is an error | |
- * | |
- * @param int result code | |
- * | |
- * @return bool whether $value is an error | |
- * | |
- * @access public | |
- */ | |
- function isError($value) | |
+ * Tell whether a value is a Tree error. | |
+ * | |
+ * @param mixed $data the value to test | |
+ * @param int $code if $data is an error object, return true | |
+ * only if $code is a string and | |
+ * $obj->getMessage() == $code or | |
+ * $code is an integer and $obj->getCode() == $code | |
+ * @access public | |
+ * @return bool true if parameter is an error | |
+ */ | |
+ function isError($data, $code = null) | |
{ | |
- return (is_object($value) && | |
- (is_a($value, 'tree_error') || | |
- is_subclass_of($value, 'tree_error'))); | |
+ if (is_a($data, 'Tree_Error')) { | |
+ if (is_null($code)) { | |
+ return true; | |
+ } elseif (is_string($code)) { | |
+ return $data->getMessage() == $code; | |
+ } else { | |
+ $code = (array)$code; | |
+ return in_array($data->getCode(), $code); | |
+ } | |
+ } | |
+ | |
+ return false; | |
} | |
// }}} | |
-} | |
\ No newline at end of file | |
+ | |
+ // {{{ getChildrenIds() | |
+ | |
+ /** | |
+ * get the ids of the children of the given element | |
+ * | |
+ * @version 2002/02/06 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer 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) | |
+ { | |
+ // returns false if no children exist | |
+ if (!($children = $this->getChildren($id, $levels))) { | |
+ return array(); | |
+ } | |
+ // return an empty array, if you want to know | |
+ // if there are children, use hasChildren | |
+ if ($children && count($children)) { | |
+ foreach ($children as $aChild) { | |
+ $childrenIds[] = $aChild['id']; | |
+ } | |
+ } | |
+ | |
+ return $childrenIds; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getAllChildren() | |
+ | |
+ /** | |
+ * gets all the children and grand children etc. | |
+ * | |
+ * @version 2002/09/30 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer 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; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ _getAllChildren() | |
+ | |
+ /** | |
+ * this method gets all the children recursively | |
+ * | |
+ * @see getAllChildren() | |
+ * @version 2002/09/30 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer 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 => $child) { | |
+ $retChildren[] = &$children[$key]; | |
+ $retChildren = array_merge($retChildren, | |
+ $this->_getAllChildren($child['id'])); | |
+ } | |
+ } | |
+ | |
+ return $retChildren; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getAllChildrenIds() | |
+ | |
+ /** | |
+ * gets all the children-ids and grand children-ids | |
+ * | |
+ * @version 2002/09/30 | |
+ * @access public | |
+ * @author Kriesing <[email protected]> | |
+ * @param integer 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 $node) { | |
+ $childrenIds[] = $node['id']; | |
+ } | |
+ } | |
+ | |
+ return $childrenIds; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getParents() | |
+ | |
+ /** | |
+ * this gets all the preceeding nodes, the parent and it's parent and so on | |
+ * | |
+ * @version 2002/08/19 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer the id of the element for which the parent_id 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 (count($path)) { | |
+ foreach ($path as $node) { | |
+ $parents[] = $node; | |
+ } | |
+ } | |
+ | |
+ return $parents; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getParentsIds() | |
+ | |
+ /** | |
+ * 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 <[email protected]> | |
+ * @param integer $id the id of the element for which the parent_id | |
+ * shall be retreived | |
+ * | |
+ * @return array of the ids | |
+ */ | |
+ function getParentsIds($id) | |
+ { | |
+ $parents = $this->getParents($id); | |
+ $parentsIds = array(); | |
+ if (count($parents)) { | |
+ foreach ($parents as $node) { | |
+ $parentsIds[] = $node['id']; | |
+ } | |
+ } | |
+ | |
+ return $parentsIds; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getPathAsString() | |
+ | |
+ /** | |
+ * returns the path as a string | |
+ * | |
+ * @access public | |
+ * @version 2002/03/28 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @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. | |
+ * @param string you can tell the key the path shall be used to be | |
+ * constructed with i.e. giving 'name' (=default) would | |
+ * use the value of the $element['name'] for the node-name | |
+ * (thanks to Michael Johnson). | |
+ * | |
+ * @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, $key = 'name') | |
+ { | |
+ $path = $this->getPath($id); | |
+ foreach ($path as $aNode) { | |
+ $pathArray[] = $aNode[$key]; | |
+ } | |
+ | |
+ if ($offset) { | |
+ if ($length) { | |
+ $pathArray = array_slice($pathArray, $offset, $length); | |
+ } else { | |
+ $pathArray = array_slice($pathArray, $offset); | |
+ } | |
+ } | |
+ | |
+ $pathString = ''; | |
+ if (count($pathArray)) { | |
+ $pathString = implode($seperator, $pathArray); | |
+ } | |
+ | |
+ return $pathString; | |
+ } | |
+ | |
+ // }}} | |
+ | |
+ | |
+ // | |
+ // abstract methods, those should be overwritten by the implementing class | |
+ // | |
+ | |
+ // {{{ getPath() | |
+ | |
+ /** | |
+ * gets the path to the element given by its id | |
+ * | |
+ * @abstract | |
+ * @version 2001/10/10 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @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 Tree::raiseError('TREE_ERROR_NOT_IMPLEMENTED'); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getLevel() | |
+ | |
+ /** | |
+ * 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 <[email protected]> | |
+ * @param mixed $id the id of the node to get the level for | |
+ * | |
+ */ | |
+ function getLevel($id) | |
+ { | |
+ return Tree::raiseError('TREE_ERROR_NOT_IMPLEMENTED'); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ isChildOf() | |
+ | |
+ /** | |
+ * returns if $childId is a child of $id | |
+ * | |
+ * @abstract | |
+ * @version 2002/04/29 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @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 Tree::raiseError('TREE_ERROR_NOT_IMPLEMENTED'); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getIdByPath() | |
+ | |
+ /** | |
+ * | |
+ * | |
+ */ | |
+ function getIdByPath($path, $startId = 0, $nodeName = 'name', $seperator = '/') | |
+ { | |
+ return Tree::raiseError('TREE_ERROR_NOT_IMPLEMENTED'); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getDepth() | |
+ | |
+ /** | |
+ * return the maximum depth of the tree | |
+ * | |
+ * @version 2003/02/25 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @return int the depth of the tree | |
+ */ | |
+ function getDepth() | |
+ { | |
+ return $this->_treeDepth; | |
+ } | |
+ | |
+ // }}} | |
+ | |
+ // | |
+ // PRIVATE METHODS | |
+ // | |
+ | |
+ // {{{ _preparePath() | |
+ | |
+ /** | |
+ * gets the path to the element given by its id | |
+ * | |
+ * @version 2003/05/11 | |
+ * @access private | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param mixed $id the id of the node to get the path for | |
+ * @return array this array contains the path elements and the sublevels | |
+ * to substract if no $cwd has been given. | |
+ */ | |
+ function _preparePath($path, $cwd = '/', $separator = '/') | |
+ { | |
+ $elems = explode($separator, $path); | |
+ $cntElems = count($elems); | |
+ | |
+ // beginning with a slash | |
+ if (empty($elems[0])) { | |
+ $beginSlash = true; | |
+ array_shift($elems); | |
+ --$cntElems; | |
+ } | |
+ | |
+ // ending with a slash | |
+ if (empty($elems[$cntElems - 1])) { | |
+ $endSlash = true; | |
+ array_pop($elems); | |
+ --$cntElems; | |
+ } | |
+ | |
+ // Get the real path, and the levels | |
+ // to substract if required | |
+ $down = 0; | |
+ while ($elems[0] == '..') { | |
+ array_shift($elems); | |
+ ++$down; | |
+ } | |
+ | |
+ if ($down >= 0 && $cwd == '/') { | |
+ $down = 0; | |
+ $_elems = array(); | |
+ $sublevel = 0; | |
+ $_elems = array(); | |
+ } else { | |
+ list($_elems, $sublevel) = $this->_preparePath($cwd); | |
+ } | |
+ | |
+ $i = 0; | |
+ foreach ($elems as $val) { | |
+ if (trim($val) == '') { | |
+ return Tree::raiseError('TREE_ERROR_INVALID_PATH'); | |
+ } | |
+ | |
+ if ($val == '..') { | |
+ $i == 0 ? ++$down : --$i; | |
+ } else { | |
+ $_elems[++$i] = $val; | |
+ } | |
+ } | |
+ | |
+ if (count($_elems) < 1) { | |
+ return Tree::raiseError('TREE_ERROR_EMPTY_PATH'); | |
+ } | |
+ | |
+ return array($_elems, $sublevel); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ _prepareResults() | |
+ | |
+ /** | |
+ * prepare multiple results | |
+ * | |
+ * @see _prepareResult() | |
+ * @access private | |
+ * @version 2002/03/03 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param array the data to prepare | |
+ * @return array prepared results | |
+ */ | |
+ function _prepareResults($results) | |
+ { | |
+ $nResults = array(); | |
+ foreach ($results as $key => $value) { | |
+ $nResults[$key] = $this->_prepareResult($value); | |
+ } | |
+ | |
+ return $nResults; | |
+ } | |
+ // }}} | |
+ // {{{ _prepareResult() | |
+ | |
+ /** | |
+ * map back the index names to get what is expected | |
+ * | |
+ * @access private | |
+ * @version 2002/03/03 | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param array a result | |
+ * @return array the prepared result | |
+ */ | |
+ function _prepareResult($result) | |
+ { | |
+ if (isset($this->conf['fields'])) { | |
+ foreach ($this->conf['fields'] as $key => $columnName) { | |
+ if (isset($result[$columnName['name']]) && $key != $columnName['name']) { | |
+ $result[$key] = $result[$columnName['name']]; | |
+ unset($result[$columnName['name']]); | |
+ } | |
+ } | |
+ } | |
+ | |
+ return $result; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ _getColName() | |
+ | |
+ /** | |
+ * this method retrieves 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 <[email protected]> | |
+ * @param string the internal name used | |
+ * @return string the real name of the column | |
+ */ | |
+ function _getColName($name) | |
+ { | |
+ if ( | |
+ isset($this->conf['fields']) && | |
+ isset($this->conf['fields'][$name]['name']) | |
+ ) { | |
+ return $this->conf['fields'][$name]['name']; | |
+ } | |
+ | |
+ return $name; | |
+ } | |
+ | |
+ // }}} | |
+ | |
+ /*******************************************************************************/ | |
+ /************************ METHODS FROM Tree_Options ****************************/ | |
+ /*******************************************************************************/ | |
+ | |
+ // {{{ setOption() | |
+ | |
+ /** | |
+ * | |
+ * @access public | |
+ * @author Stig S. Baaken | |
+ * @param string the option name | |
+ * @param mixed the value for this option | |
+ * @param boolean if set to true options are also set | |
+ * even if no key(s) was/were found in the options property | |
+ */ | |
+ function setOption($option, $value, $force = false) | |
+ { | |
+ if ($option == 'fields') { | |
+ return false; | |
+ } | |
+ // if the value is an array extract the keys | |
+ // and apply only each value that is set | |
+ if (is_array($value)) { | |
+ // so we dont override existing options inside an array | |
+ // if an option is an array | |
+ foreach ($value as $key => $aValue) { | |
+ Tree::setOption(array($option, $key), $aValue); | |
+ } | |
+ | |
+ return true; | |
+ } | |
+ | |
+ if (is_array($option)) { | |
+ $mainOption = $option[0]; | |
+ $options = "['".implode("']['",$option)."']"; | |
+ $evalCode = "\$this->conf".$options." = \$value;"; | |
+ } else { | |
+ $evalCode = "\$this->conf[\$option] = \$value;"; | |
+ $mainOption = $option; | |
+ } | |
+ | |
+ if ( | |
+ $force == true | |
+ || isset($this->conf[$mainOption]) | |
+ ) { | |
+ eval($evalCode); | |
+ return true; | |
+ } | |
+ return false; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ setOptions() | |
+ | |
+ /** | |
+ * set a number of options which are simply given in an array | |
+ * | |
+ * @access public | |
+ * @param array the values to set | |
+ * @param boolean if set to true options are also set even if no key(s) | |
+ * was/were found in the options property | |
+ */ | |
+ function setOptions($options, $force = false) | |
+ { | |
+ if (is_array($options) && count($options)) { | |
+ foreach ($options as $key => $value) { | |
+ $this->setOption($key, $value, $force); | |
+ } | |
+ } | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getOption() | |
+ | |
+ /** | |
+ * | |
+ * @access public | |
+ * @author copied from PEAR: DB/commmon.php | |
+ * @param boolean true on success | |
+ */ | |
+ function getOption($option) | |
+ { | |
+ if (isset($this->conf[$option])) { | |
+ return $this->conf[$option]; | |
+ } | |
+ return false; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ getOptions() | |
+ | |
+ /** | |
+ * returns all the options | |
+ * | |
+ * @version 02/05/20 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @return string all options as an array | |
+ */ | |
+ function getOptions() | |
+ { | |
+ return $this->conf; | |
+ } | |
+ | |
+ // }}} | |
+} | |
+ | |
+/** | |
+ * Tree_Error implements a class for reporting portable database error | |
+ * messages. | |
+ * | |
+ * @package Tree | |
+ */ | |
+class Tree_Error extends PEAR_Error | |
+{ | |
+ /** | |
+ * Tree_Error constructor. | |
+ * | |
+ * @param mixed $code Tree error code, or string with error message. | |
+ * @param integer $mode what 'error mode' to operate in | |
+ * @param integer $level what error level to use for | |
+ * $mode & PEAR_ERROR_TRIGGER | |
+ * @param smixed $debuginfo additional debug info, such as the last query | |
+ */ | |
+ function Tree_Error($code = TREE_ERROR, $mode = PEAR_ERROR_RETURN, | |
+ $level = E_USER_NOTICE, $debuginfo = NULL) | |
+ { | |
+ if (is_int($code)) { | |
+ $this->PEAR_Error('Tree Error: ' . Tree::errorMessage($code), $code, | |
+ $mode, $level, $debuginfo); | |
+ } else { | |
+ $this->PEAR_Error("Tree Error: $code", TREE_ERROR, $mode, $level, | |
+ $debuginfo); | |
+ } | |
+ } | |
+} | |
+?> | |
Property changes on: Tree/Tree.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.13.2.2 | |
+1.14 | |
Index: Tree/Admin/Simple.php | |
=================================================================== | |
Property changes on: Tree/Admin/Simple.php | |
___________________________________________________________________ | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Index: Tree/Admin/Dynamic/MDBnested.php | |
=================================================================== | |
--- Tree/Admin/Dynamic/MDBnested.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Admin/Dynamic/MDBnested.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,35 @@ | |
+<?php | |
+/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
+// +----------------------------------------------------------------------+ | |
+// | PHP Version 4 | | |
+// +----------------------------------------------------------------------+ | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
+// +----------------------------------------------------------------------+ | |
+// | This source file is subject to version 3.0 of the PHP license, | | |
+// | that is bundled with this package in the file LICENSE, and is | | |
+// | available at through the world-wide-web at | | |
+// | http://www.php.net/license/3_0.txt. | | |
+// | If you did not receive a copy of the PHP license and are unable to | | |
+// | obtain it through the world-wide-web, please send a note to | | |
+// | [email protected] so we can mail you a copy immediately. | | |
+// +----------------------------------------------------------------------+ | |
+// | Authors: | | |
+// +----------------------------------------------------------------------+ | |
+// | |
+// $Id$ | |
+ | |
+require_once 'Tree/Dynamic/MDBnested.php'; | |
+ | |
+/** | |
+* This class implements methods to work on a tree saved using the nested | |
+* tree model. | |
+* explaination: http://research.calacademy.org/taf/proceedings/ballew/index.htm | |
+* | |
+* @access public | |
+* @package Tree | |
+*/ | |
+class Tree_Dynamic_Admin_MDBnested extends Tree_Dynamic_MDBnested | |
+{ | |
+ | |
+} | |
+?> | |
\ No newline at end of file | |
Property changes on: Tree/Admin/Dynamic/MDBnested.php | |
___________________________________________________________________ | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Index: Tree/Admin/Dynamic/DBnested.php | |
=================================================================== | |
--- Tree/Admin/Dynamic/DBnested.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Admin/Dynamic/DBnested.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,36 @@ | |
+<?php | |
+/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
+// +----------------------------------------------------------------------+ | |
+// | PHP Version 4 | | |
+// +----------------------------------------------------------------------+ | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
+// +----------------------------------------------------------------------+ | |
+// | This source file is subject to version 3.0 of the PHP license, | | |
+// | that is bundled with this package in the file LICENSE, and is | | |
+// | available at through the world-wide-web at | | |
+// | http://www.php.net/license/3_0.txt. | | |
+// | If you did not receive a copy of the PHP license and are unable to | | |
+// | obtain it through the world-wide-web, please send a note to | | |
+// | [email protected] so we can mail you a copy immediately. | | |
+// +----------------------------------------------------------------------+ | |
+// | Authors: | | |
+// +----------------------------------------------------------------------+ | |
+// | |
+// $Id$ | |
+ | |
+require_once 'Tree/Dynamic/DBnested.php'; | |
+ | |
+/** | |
+* This class implements methods to work on a tree saved using the nested | |
+* tree model. | |
+* explaination: http://research.calacademy.org/taf/proceedings/ballew/index.htm | |
+* | |
+* @access public | |
+* @package Tree | |
+*/ | |
+class Tree_Dynamic_Admin_DBnested extends Tree_Dynamic_DBnested | |
+{ | |
+ | |
+ | |
+} | |
+?> | |
\ No newline at end of file | |
Property changes on: Tree/Admin/Dynamic/DBnested.php | |
___________________________________________________________________ | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Index: Tree/Memory/MDBsimple.php | |
=================================================================== | |
--- Tree/Memory/MDBsimple.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory/MDBsimple.php (.../trunk) (revision 321102) | |
@@ -1,448 +0,0 @@ | |
-<?php | |
- | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: Wolfram Kriesing <[email protected]> | | |
-// | Lorenzo Alberton <[email protected]> | | |
-// +----------------------------------------------------------------------+ | |
- | |
-// $Id$ | |
-require_once 'Tree/OptionsMDB.php'; | |
-require_once 'Tree/Error.php'; | |
- | |
-/** | |
-* the MDB interface to the tree class | |
-* | |
-* @access public | |
-* @author Lorenzo Alberton <[email protected]> | |
-* @package Tree | |
-*/ | |
-class Tree_Memory_MDBsimple extends Tree_OptionsMDB | |
-{ | |
- // FIXXME should actually extend Tree_Common, to use the methods provided in there... | |
- // but we need to connect to the db here, so we extend optionsMDB for now, may be use | |
- // "aggregate" function to fix that | |
- | |
- /** | |
- * @access public | |
- * @var array saves the options passed to the constructor. Valid options: | |
- * - order: which column to order by when reading the data from the DB, | |
- * this sorts the data even inside every level | |
- * - whereAddOn: add on for the where clause, this string is simply | |
- * added behind the WHERE in the select, so you better make | |
- * sure its correct SQL :-), i.e. 'uid=3'. | |
- * This is needed i.e. when you are saving many trees for different | |
- * user in one table where each entry has a uid (user id) | |
- * - columnNameMaps: the column-name maps are used for the "as" in the select | |
- * queries so you can use any column name in the table and "map" | |
- * it to the name that shall be used in the internal array, | |
- * that is built, see the examples (in comments) | |
- * - columnNameMaps: array for id/parentId/prevId/name table column names | |
- */ | |
- var $options = array('order' => '', | |
- 'whereAddOn' => '', | |
- 'table' => '', | |
- 'columnNameMaps' => array( | |
- /* 'id' => 'tree_id', // use "tree_id" as "id" | |
- 'parentId' => 'parent_id', | |
- 'prevId' => 'previous_id', | |
- 'name' => 'nodeName' | |
- */ | |
- ), | |
- ); | |
- | |
- /** | |
- * @access public | |
- * @var string the table where to read the tree data from | |
- * can also be set using the DSN in the constructor | |
- */ | |
- var $table; | |
- | |
- /** | |
- * @access private | |
- * @var object $dbh the handle to the DB-object | |
- */ | |
- // var $dbh; | |
- | |
- // {{{ Tree_Memory_MDBsimple() | |
- | |
- /** | |
- * set up this object | |
- * | |
- * @access public | |
- * @param string $dsn this is a DSN of the for that PEAR::DB uses it | |
- * only that additionally you can add parameters like ...?table=test_table | |
- * to define the table it shall work on | |
- * @param array $options additional options you can set | |
- */ | |
- function Tree_Memory_MDBsimple($dsn, $options = array()) | |
- { | |
- $this->Tree_OptionsMDB($dsn, $options); // instanciate DB | |
- if (is_string($options)) { | |
- // just to be backward compatible, or to make the second paramter shorter | |
- $this->setOption('order', $options); | |
- } | |
- | |
- $this->table = $this->getOption('table'); | |
- } | |
- | |
- // }}} | |
- // {{{ setup() | |
- | |
- /** | |
- * retrieve all the navigation data from the db and call build to build the | |
- * tree in the array data and structure | |
- * | |
- * @access public | |
- * @return boolean true on success | |
- */ | |
- function setup() | |
- { | |
- // TODO sort by prevId (parentId, prevId $addQuery) too if it exists in the table, | |
- // or the root might be wrong, since the prevId of the root should be 0 | |
- | |
- $whereAddOn = ''; | |
- if ($this->options['whereAddOn']) { | |
- $whereAddOn = 'WHERE ' . $this->getOption('whereAddOn'); | |
- } | |
- | |
- $orderBy = ''; | |
- if ($this->options['order']) { | |
- $orderBy = ',' . $this->options['order']; | |
- } | |
- | |
- $map = $this->getOption('columnNameMaps'); | |
- if (isset($map['parentId'])) { | |
- $orderBy = $map['parentId'] . $orderBy; | |
- } else { | |
- $orderBy = 'parentId' . $orderBy; | |
- } | |
- // build the query this way, that the root, which has no parent (parentId=0) | |
- // and no previous (prevId=0) is in first place (in case prevId is given) | |
- $query = sprintf("SELECT * FROM %s %s ORDER BY %s", | |
- $this->table, | |
- $whereAddOn, | |
- $orderBy); //,prevId !!!! | |
- if (MDB::isError($res = $this->dbh->getAll($query))) { | |
- // FIXXME remove print use debug mode instead | |
- printf("ERROR - Tree::setup - %s - %s<br />", MDB::errorMessage($res), $query); | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- // if the db-column names need to be mapped to different names | |
- // FIXXME somehow we should be able to do this in the query, but I dont know | |
- // how to select only those columns, use "as" on them and select the rest, | |
- //without getting those columns again :-( | |
- if ($map) { | |
- foreach ($res as $id => $aResult) { // map each result | |
- foreach ($map as $key => $columnName) { | |
- $res[$id][$key] = $res[$id][$columnName]; | |
- unset($res[$id][$columnName]); | |
- } | |
- } | |
- } | |
- | |
- return $res; | |
- } | |
- | |
- // }}} | |
- // {{{ add() | |
- | |
- /** | |
- * adds _one_ new element in the tree under the given parent | |
- * the values' keys given have to match the db-columns, because the | |
- * value gets inserted in the db directly | |
- * to add an entire node containing children and so on see 'addNode()' | |
- * | |
- * to be compatible with the MDBnested, u can also give the parent and previd | |
- * as the second and third parameter | |
- * | |
- * @see addNode | |
- * @access public | |
- * @param array $newValues this array contains the values that shall be inserted in the db-table | |
- * the key for each element is the name of the column | |
- * @return mixed either boolean false on failure or the id of the inserted row | |
- */ | |
- function add($newValues, $parentId = 0) | |
- { | |
- // FIXXME use $this->dbh->tableInfo to check which columns exist | |
- // so only data for which a column exist is inserted | |
- if ($parentId) { | |
- $newValues['parentId'] = $parentId; | |
- } | |
- $newData = array(); | |
- foreach ($newValues as $key => $value) { | |
- // quote the values, as needed for the insert | |
- $newData[$this->_getColName($key)] = $this->_quote($value); | |
- } | |
- // use sequences to create a new id in the db-table | |
- $nextId = $this->dbh->nextId($this->table); | |
- $query = sprintf("INSERT INTO %s (%s,%s) VALUES (%s,%s)", | |
- $this->table , | |
- $this->_getColName('id'), | |
- implode(',', array_keys($newData)) , | |
- $nextId, | |
- implode(',', $newData)); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // TODO raise PEAR error | |
- printf("ERROR - Tree::add - %s - %s<br />", MDB::errorMessage($res), $query); | |
- return false; | |
- } | |
- | |
- return $nextId; | |
- } | |
- | |
- // }}} | |
- // {{{ remove() | |
- | |
- /** | |
- * removes the given node | |
- * | |
- * @access public | |
- * @param mixed $id the id of the node to be removed, or an array of id's to be removed | |
- * @return boolean true on success | |
- */ | |
- function remove($id) | |
- { | |
- // if the one to remove has children, get their id's to remove them too | |
- if ($this->hasChildren($id)) { | |
- $id = $this->walk(array('_remove', $this), $id, 'array'); | |
- } | |
- $idColumnName = 'id'; | |
- $map = $this->getOption('columnNameMaps'); | |
- if (isset($map['id'])) { // if there are maps given | |
- $idColumnName = $map['id']; | |
- } | |
- | |
- $whereClause = "WHERE $idColumnName=$id"; | |
- if (is_array($id)) { | |
- $whereClause = "WHERE $idColumnName in (" . implode(',', $id) . ')'; | |
- } | |
- | |
- $query = "DELETE FROM {$this->table} $whereClause"; | |
- // print('<br />'.$query); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // TODO raise PEAR error | |
- printf("ERROR - Tree::remove - %s - %s<br>", MDB::errormessage($res), $query); | |
- return false; | |
- } | |
- // TODO if remove succeeded set prevId of the following element properly | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ move() | |
- | |
- /** | |
- * move an entry under a given parent or behind a given entry | |
- * | |
- * @version 2001/10/10 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer $idToMove the id of the element that shall be moved | |
- * @param integer $newParentId the id of the element which will be the new parent | |
- * @param integer $newPrevId if prevId is given the element with the id idToMove | |
- * shall be moved _behind_ the element with id=prevId | |
- * if it is 0 it will be put at the beginning | |
- * if no prevId is in the DB it can be 0 too and won't bother | |
- * since it is not written in the DB anyway | |
- * @return boolean true for success | |
- */ | |
- function move($idToMove, $newParentId, $newPrevId = 0) | |
- { | |
- $idColumnName = 'id'; | |
- $parentIdColumnName = 'parentId'; | |
- $map = $this->getOption('columnNameMaps'); | |
- if (isset($map['id'])) { | |
- $idColumnName = $map['id']; | |
- } | |
- if (isset($map['parentId'])) { | |
- $parentIdColumnName = $map['parentId']; | |
- } | |
- // FIXXME todo: previous stuff | |
- // set the parent in the DB | |
- $query = "UPDATE $this->table SET $parentIdColumnName=$newParentId WHERE $idColumnName=$idToMove"; | |
- // print($query); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // TODO raise PEAR error | |
- printf("ERROR - Tree::move - %s - %s<br>", MDB::errorMessage($res), $query); | |
- return false; | |
- } | |
- // FIXXME update the prevId's of the elements where the element was moved away from and moved in | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ update() | |
- | |
- /** | |
- * update an element in the DB | |
- * | |
- * @version 2002/01/17 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array $newData all the new data, the key 'id' is used to | |
- build the 'WHERE id=' clause and all the other | |
- * elements are the data to fill in the DB | |
- * @return boolean true for success | |
- */ | |
- function update($id, $newData) | |
- { | |
- // FIXXME check $this->dbh->tableInfo to see if all the columns that shall be updated | |
- // really exist, this will also extract nextId etc. if given before writing it in the DB | |
- // in case they dont exist in the DB | |
- $setData = array(); | |
- foreach ($newData as $key => $value) { // quote the values, as needed for the insert | |
- $setData[] = $this->_getColName($key) . '=' . $this->_quote($value); | |
- } | |
- | |
- $query = sprintf('UPDATE %s SET %s WHERE %s=%s', | |
- $this->table, | |
- implode(',', $setData), | |
- $this->_getColName('id'), | |
- $id | |
- ); | |
- if (MDB::isError($res = $this->dbh->query($query))) { | |
- // FIXXME raise PEAR error | |
- printf("ERROR - Tree::update - %s - %s<br>", MDB::errormessage($res), $query); | |
- return false; | |
- } | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ _throwError() | |
- | |
- /** | |
- * | |
- * @access private | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _throwError($msg, $line, $mode = null) | |
- { | |
- return new Tree_Error($msg, $line, __FILE__, $mode, $this->dbh->last_query); | |
- } | |
- | |
- // }}} | |
- // {{{ _prepareResults() | |
- | |
- /** | |
- * prepare multiple results | |
- * | |
- * @see _prepareResult | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _prepareResults($results) | |
- { | |
- $newResults = array(); | |
- foreach ($results as $aResult) { | |
- $newResults[] = $this->_prepareResult($aResult); | |
- } | |
- return $newResults; | |
- } | |
- | |
- // }}} | |
- // {{{ _prepareResult() | |
- | |
- /** | |
- * map back the index names to get what is expected | |
- * | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _prepareResult($result) | |
- { | |
- $map = $this->getOption('columnNameMaps'); | |
- | |
- if ($map) { | |
- foreach ($map as $key => $columnName) { | |
- $result[$key] = $result[$columnName]; | |
- unset($result[$columnName]); | |
- } | |
- } | |
- return $result; | |
- } | |
- | |
- // }}} | |
- // {{{ _getColName() | |
- | |
- /** | |
- * 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 <[email protected]> | |
- */ | |
- function _getColName($internalName) | |
- { | |
- if ($map = $this->getOption('columnNameMaps')) { | |
- if (isset($map[$internalName])) { | |
- return $map[$internalName]; | |
- } | |
- } | |
- return $internalName; | |
- } | |
- | |
- // }}} | |
- // {{{ _quoteArray() | |
- | |
- /** | |
- * quotes all the data in this array | |
- * | |
- * @param array $data Array to quote | |
- */ | |
- function _quoteArray($data) | |
- { | |
- foreach ($data as $key => $val) { | |
- $data[$key] = $this->_quote($val); | |
- } | |
- return $data; | |
- } | |
- | |
- // }}} | |
- // {{{ _quote() | |
- | |
- /** | |
- * quotes all the data in this var (can be any type except object) | |
- * @param mixed $data data to quote | |
- */ | |
- function _quote($data) | |
- { | |
- switch(gettype($data)) { | |
- case 'array': | |
- return $this->_quoteArray($data); | |
- break; | |
- case 'boolean': | |
- return $this->dbh->getBooleanValue($data); | |
- break; | |
- case 'double': | |
- return $this->dbh->getFloatValue($data); | |
- break; | |
- case 'integer': | |
- return $this->dbh->getIntegerValue($data); | |
- break; | |
- case 'string': //if 'string' or 'unknown', quote as text | |
- default: | |
- return $this->dbh->getTextValue($data); | |
- } | |
- } | |
- | |
- // }}} | |
-} | |
\ No newline at end of file | |
Index: Tree/Memory/MDB2simple.php | |
=================================================================== | |
--- Tree/Memory/MDB2simple.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory/MDB2simple.php (.../trunk) (revision 321102) | |
@@ -1,443 +0,0 @@ | |
-<?php | |
- | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: Wolfram Kriesing <[email protected]> | | |
-// | Lorenzo Alberton <[email protected]> | | |
-// +----------------------------------------------------------------------+ | |
- | |
-// $Id$ | |
-require_once 'Tree/OptionsMDB2.php'; | |
- | |
-/** | |
-* the MDB2 interface to the tree class | |
-* | |
-* @access public | |
-* @author Lorenzo Alberton <[email protected]> | |
-* @package Tree | |
-*/ | |
-class Tree_Memory_MDB2simple extends Tree_OptionsMDB2 | |
-{ | |
- // FIXXME should actually extend Tree_Common, to use the methods provided in there... | |
- // but we need to connect to the db here, so we extend optionsMDB2 for now, may be use | |
- // "aggregate" function to fix that | |
- | |
- /** | |
- * @access public | |
- * @var array saves the options passed to the constructor. Valid options: | |
- * - order: which column to order by when reading the data from the DB, | |
- * this sorts the data even inside every level | |
- * - whereAddOn: add on for the where clause, this string is simply | |
- * added behind the WHERE in the select, so you better make | |
- * sure its correct SQL :-), i.e. 'uid=3'. | |
- * This is needed i.e. when you are saving many trees for different | |
- * user in one table where each entry has a uid (user id) | |
- * - columnNameMaps: the column-name maps are used for the "as" in the select | |
- * queries so you can use any column name in the table and "map" | |
- * it to the name that shall be used in the internal array, | |
- * that is built, see the examples (in comments) | |
- * - columnNameMaps: array for id/parentId/prevId/name table column names | |
- */ | |
- var $options = array('order' => '', | |
- 'whereAddOn' => '', | |
- 'table' => '', | |
- 'columnNameMaps' => array( | |
- /* 'id' => 'tree_id', // use "tree_id" as "id" | |
- 'parentId' => 'parent_id', | |
- 'prevId' => 'previous_id', | |
- 'name' => 'nodeName' | |
- */ | |
- ), | |
- ); | |
- | |
- /** | |
- * @access public | |
- * @var string the table where to read the tree data from | |
- * can also be set using the DSN in the constructor | |
- */ | |
- var $table; | |
- | |
- /** | |
- * @access private | |
- * @var object $dbh the handle to the DB-object | |
- */ | |
- // var $dbh; | |
- | |
- // {{{ Tree_Memory_MDB2simple() | |
- | |
- /** | |
- * set up this object | |
- * | |
- * @access public | |
- * @param string $dsn this is a DSN of the for that PEAR::DB uses it | |
- * only that additionally you can add parameters like ...?table=test_table | |
- * to define the table it shall work on | |
- * @param array $options additional options you can set | |
- */ | |
- function Tree_Memory_MDB2simple($dsn, $options = array()) | |
- { | |
- $this->Tree_OptionsMDB2($dsn, $options); // instanciate DB | |
- if (is_string($options)) { | |
- // just to be backward compatible, or to make the second paramter shorter | |
- $this->setOption('order', $options); | |
- } | |
- | |
- $this->table = $this->getOption('table'); | |
- } | |
- | |
- // }}} | |
- // {{{ setup() | |
- | |
- /** | |
- * retrieve all the navigation data from the db and call build to build the | |
- * tree in the array data and structure | |
- * | |
- * @access public | |
- * @return boolean true on success | |
- */ | |
- function setup() | |
- { | |
- // TODO sort by prevId (parentId, prevId $addQuery) too if it exists in the table, | |
- // or the root might be wrong, since the prevId of the root should be 0 | |
- | |
- $whereAddOn = ''; | |
- if ($this->options['whereAddOn']) { | |
- $whereAddOn = 'WHERE ' . $this->getOption('whereAddOn'); | |
- } | |
- | |
- $orderBy = ''; | |
- if ($this->options['order']) { | |
- $orderBy = ',' . $this->options['order']; | |
- } | |
- | |
- $map = $this->getOption('columnNameMaps'); | |
- if (isset($map['parentId'])) { | |
- $orderBy = $map['parentId'] . $orderBy; | |
- } else { | |
- $orderBy = 'parentId' . $orderBy; | |
- } | |
- // build the query this way, that the root, which has no parent (parentId=0) | |
- // and no previous (prevId=0) is in first place (in case prevId is given) | |
- $query = sprintf("SELECT * FROM %s %s ORDER BY %s", | |
- $this->table, | |
- $whereAddOn, | |
- $orderBy); //,prevId !!!! | |
- if (MDB2::isError($res = $this->dbh->queryAll($query))) { | |
- // FIXXME remove print use debug mode instead | |
- printf("ERROR - Tree::setup - %s - %s<br />", MDB2::errorMessage($res), $query); | |
- return Tree::raiseError('TREE_ERROR_RAISE_ERROR', $res->getMessage()); | |
- } | |
- | |
- // Account for the fact the by default MDB2 lower cases field names | |
- // But only if people are not doing the mapping them self | |
- if (!isset($map['parentId']) || $map['parentId'] != 'parentid') { | |
- foreach ($res as $index => $value) { | |
- $res[$index]['parentId'] = $res[$index]['parentid']; | |
- unset($res[$index]['parentid']); | |
- } | |
- } | |
- | |
- // if the db-column names need to be mapped to different names | |
- // FIXXME somehow we should be able to do this in the query, but I dont know | |
- // how to select only those columns, use "as" on them and select the rest, | |
- //without getting those columns again :-( | |
- if ($map) { | |
- foreach ($res as $id => $aResult) { // map each result | |
- foreach ($map as $key => $columnName) { | |
- $res[$id][$key] = $res[$id][$columnName]; | |
- unset($res[$id][$columnName]); | |
- } | |
- } | |
- } | |
- | |
- return $res; | |
- } | |
- | |
- // }}} | |
- // {{{ add() | |
- | |
- /** | |
- * adds _one_ new element in the tree under the given parent | |
- * the values' keys given have to match the db-columns, because the | |
- * value gets inserted in the db directly | |
- * to add an entire node containing children and so on see 'addNode()' | |
- * | |
- * to be compatible with the MDB2nested, u can also give the parent and previd | |
- * as the second and third parameter | |
- * | |
- * @see addNode | |
- * @access public | |
- * @param array $newValues this array contains the values that shall be inserted in the db-table | |
- * the key for each element is the name of the column | |
- * @return mixed either boolean false on failure or the id of the inserted row | |
- */ | |
- function add($newValues, $parentId = 0) | |
- { | |
- // FIXXME use $this->dbh->tableInfo to check which columns exist | |
- // so only data for which a column exist is inserted | |
- if ($parentId) { | |
- $newValues['parentId'] = $parentId; | |
- } | |
- $newData = array(); | |
- foreach ($newValues as $key => $value) { | |
- // quote the values, as needed for the insert | |
- $newData[$this->_getColName($key)] = $this->_quote($value); | |
- } | |
- // use sequences to create a new id in the db-table | |
- $nextId = $this->dbh->nextId($this->table); | |
- $query = sprintf("INSERT INTO %s (%s,%s) VALUES (%s,%s)", | |
- $this->table , | |
- $this->_getColName('id'), | |
- implode(',', array_keys($newData)) , | |
- $nextId, | |
- implode(',', $newData)); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // TODO raise PEAR error | |
- printf("ERROR - Tree::add - %s - %s<br />", MDB2::errorMessage($res), $query); | |
- return false; | |
- } | |
- | |
- return $nextId; | |
- } | |
- | |
- // }}} | |
- // {{{ remove() | |
- | |
- /** | |
- * removes the given node | |
- * | |
- * @access public | |
- * @param mixed $id the id of the node to be removed, or an array of id's to be removed | |
- * @return boolean true on success | |
- */ | |
- function remove($id) | |
- { | |
- // if the one to remove has children, get their id's to remove them too | |
- if ($this->hasChildren($id)) { | |
- $id = $this->walk(array('_remove', $this), $id, 'array'); | |
- } | |
- $idColumnName = 'id'; | |
- $map = $this->getOption('columnNameMaps'); | |
- if (isset($map['id'])) { // if there are maps given | |
- $idColumnName = $map['id']; | |
- } | |
- | |
- $whereClause = "WHERE $idColumnName=$id"; | |
- if (is_array($id)) { | |
- $whereClause = "WHERE $idColumnName in (" . implode(',', $id) . ')'; | |
- } | |
- | |
- $query = "DELETE FROM {$this->table} $whereClause"; | |
- // print('<br />'.$query); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // TODO raise PEAR error | |
- printf("ERROR - Tree::remove - %s - %s<br>", MDB2::errormessage($res), $query); | |
- return false; | |
- } | |
- // TODO if remove succeeded set prevId of the following element properly | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ move() | |
- | |
- /** | |
- * move an entry under a given parent or behind a given entry | |
- * | |
- * @version 2001/10/10 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer $idToMove the id of the element that shall be moved | |
- * @param integer $newParentId the id of the element which will be the new parent | |
- * @param integer $newPrevId if prevId is given the element with the id idToMove | |
- * shall be moved _behind_ the element with id=prevId | |
- * if it is 0 it will be put at the beginning | |
- * if no prevId is in the DB it can be 0 too and won't bother | |
- * since it is not written in the DB anyway | |
- * @return boolean true for success | |
- */ | |
- function move($idToMove, $newParentId, $newPrevId = 0) | |
- { | |
- $idColumnName = 'id'; | |
- $parentIdColumnName = 'parentId'; | |
- $map = $this->getOption('columnNameMaps'); | |
- if (isset($map['id'])) { | |
- $idColumnName = $map['id']; | |
- } | |
- if (isset($map['parentId'])) { | |
- $parentIdColumnName = $map['parentId']; | |
- } | |
- // FIXXME todo: previous stuff | |
- // set the parent in the DB | |
- $query = "UPDATE $this->table SET $parentIdColumnName=$newParentId WHERE $idColumnName=$idToMove"; | |
- // print($query); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // TODO raise PEAR error | |
- printf("ERROR - Tree::move - %s - %s<br>", MDB2::errorMessage($res), $query); | |
- return false; | |
- } | |
- // FIXXME update the prevId's of the elements where the element was moved away from and moved in | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ update() | |
- | |
- /** | |
- * update an element in the DB | |
- * | |
- * @version 2002/01/17 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array $newData all the new data, the key 'id' is used to | |
- build the 'WHERE id=' clause and all the other | |
- * elements are the data to fill in the DB | |
- * @return boolean true for success | |
- */ | |
- function update($id, $newData) | |
- { | |
- // FIXXME check $this->dbh->tableInfo to see if all the columns that shall be updated | |
- // really exist, this will also extract nextId etc. if given before writing it in the DB | |
- // in case they dont exist in the DB | |
- $setData = array(); | |
- foreach ($newData as $key => $value) { // quote the values, as needed for the insert | |
- $setData[] = $this->_getColName($key) . '=' . $this->_quote($value); | |
- } | |
- | |
- $query = sprintf('UPDATE %s SET %s WHERE %s=%s', | |
- $this->table, | |
- implode(',', $setData), | |
- $this->_getColName('id'), | |
- $id | |
- ); | |
- if (MDB2::isError($res = $this->dbh->exec($query))) { | |
- // FIXXME raise PEAR error | |
- printf("ERROR - Tree::update - %s - %s<br>", MDB2::errormessage($res), $query); | |
- return false; | |
- } | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ _prepareResults() | |
- | |
- /** | |
- * prepare multiple results | |
- * | |
- * @see _prepareResult | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _prepareResults($results) | |
- { | |
- $newResults = array(); | |
- foreach ($results as $aResult) { | |
- $newResults[] = $this->_prepareResult($aResult); | |
- } | |
- return $newResults; | |
- } | |
- | |
- // }}} | |
- // {{{ _prepareResult() | |
- | |
- /** | |
- * map back the index names to get what is expected | |
- * | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _prepareResult($result) | |
- { | |
- $map = $this->getOption('columnNameMaps'); | |
- | |
- if ($map) { | |
- foreach ($map as $key => $columnName) { | |
- $result[$key] = $result[$columnName]; | |
- unset($result[$columnName]); | |
- } | |
- } | |
- return $result; | |
- } | |
- | |
- // }}} | |
- // {{{ _getColName() | |
- | |
- /** | |
- * 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 <[email protected]> | |
- */ | |
- function _getColName($internalName) | |
- { | |
- if ($map = $this->getOption('columnNameMaps')) { | |
- if (isset($map[$internalName])) { | |
- return $map[$internalName]; | |
- } | |
- } | |
- return $internalName; | |
- } | |
- | |
- // }}} | |
- // {{{ _quoteArray() | |
- | |
- /** | |
- * quotes all the data in this array | |
- * | |
- * @param array $data Array to quote | |
- */ | |
- function _quoteArray($data) | |
- { | |
- foreach ($data as $key => $val) { | |
- $data[$key] = $this->_quote($val); | |
- } | |
- return $data; | |
- } | |
- | |
- // }}} | |
- // {{{ _quote() | |
- | |
- /** | |
- * quotes all the data in this var (can be any type except object) | |
- * @param mixed $data data to quote | |
- */ | |
- function _quote($data) | |
- { | |
- switch(gettype($data)) { | |
- case 'array': | |
- return $this->_quoteArray($data); | |
- break; | |
- case 'boolean': | |
- return $this->dbh->quote($data); | |
- break; | |
- case 'double': | |
- return $this->dbh->quote($data); | |
- break; | |
- case 'integer': | |
- return $this->dbh->quote($data); | |
- break; | |
- case 'string': //if 'string' or 'unknown', quote as text | |
- default: | |
- return $this->dbh->quote($data); | |
- } | |
- } | |
- | |
- // }}} | |
-} | |
\ No newline at end of file | |
Index: Tree/Memory/DBsimple.php | |
=================================================================== | |
--- Tree/Memory/DBsimple.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory/DBsimple.php (.../trunk) (revision 321102) | |
@@ -1,409 +0,0 @@ | |
-<?php | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: Wolfram Kriesing <[email protected]> | | |
-// +----------------------------------------------------------------------+ | |
- | |
-// $Id$ | |
-require_once 'Tree/OptionsDB.php'; | |
-require_once 'Tree/Error.php'; | |
- | |
-/** | |
- * the DB interface to the tree class | |
- * | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @version 2001/06/27 | |
- * @package Tree | |
- */ | |
-class Tree_Memory_DBsimple extends Tree_OptionsDB | |
-{ | |
- // FIXXME should actually extend Tree_Common, to use the methods provided in there... | |
- // but we need to connect to the db here, so we extend optionsMDB for now, may be use | |
- // "aggregate" function to fix that | |
- | |
- /** | |
- * @access public | |
- * @var array saves the options passed to the constructor. Valid options: | |
- * - order: which column to order by when reading the data from the DB, | |
- * this sorts the data even inside every level | |
- * - whereAddOn: add on for the where clause, this string is simply | |
- * added behind the WHERE in the select, so you better make | |
- * sure its correct SQL :-), i.e. 'uid=3'. | |
- * This is needed i.e. when you are saving many trees for different | |
- * user in one table where each entry has a uid (user id) | |
- * - columnNameMaps: the column-name maps are used for the "as" in the select | |
- * queries so you can use any column name in the table and "map" | |
- * it to the name that shall be used in the internal array, | |
- * that is built, see the examples (in comments) | |
- * - columnNameMaps: array for id/parentId/prevId/name table column names | |
- */ | |
- var $options = array('order' => '', | |
- 'whereAddOn' => '', | |
- 'table' => '', | |
- 'columnNameMaps' => array( | |
- /* 'id' => 'tree_id', // use "tree_id" as "id" | |
- 'parentId' => 'parent_id', | |
- 'prevId' => 'previous_id', | |
- 'name' => 'nodeName' | |
- */ | |
- ), | |
- ); | |
- | |
- /** | |
- * | |
- * @access public | |
- * @var string the table where to read the tree data from | |
- * can also be set using the DSN in the constructor | |
- */ | |
- var $table; | |
- | |
- /** | |
- * | |
- * @access private | |
- * @var object $dbh the handle to the DB-object | |
- */ | |
- // var $dbh; | |
- | |
- // {{{ Tree_Memory_DBsimple() | |
- | |
- /** | |
- * set up this object | |
- * | |
- * @version 2001/06/27 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param string $dsn this is a DSN of the for that PEAR::DB uses it | |
- * only that additionally you can add parameters like ...?table=test_table | |
- * to define the table it shall work on | |
- * @param array $options additional options you can set | |
- */ | |
- function Tree_Memory_DBsimple($dsn, $options = array()) | |
- { | |
- $this->Tree_OptionsDB($dsn, $options); // instanciate DB | |
- if (is_string($options)) { | |
- // just to be backward compatible, or to make the second paramter shorter | |
- $this->setOption('order', $options); | |
- } | |
- | |
- $this->table = $this->getOption('table'); | |
- } | |
- | |
- // }}} | |
- // {{{ setup() | |
- | |
- /** | |
- * retreive all the navigation data from the db and call build to build the | |
- * tree in the array data and structure | |
- * | |
- * @version 2001/11/20 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @return boolean true on success | |
- */ | |
- function setup() | |
- { | |
- // TODO sort by prevId (parentId,prevId $addQuery) too if it exists in the table, or the root might be wrong | |
- // TODO since the prevId of the root should be 0 | |
- | |
- $whereAddOn = ''; | |
- if ($this->options['whereAddOn']) { | |
- $whereAddOn = 'WHERE ' . $this->getOption('whereAddOn'); | |
- } | |
- | |
- $orderBy = ''; | |
- if ($this->options['order']) { | |
- $orderBy = ',' . $this->options['order']; | |
- } | |
- | |
- $map = $this->getOption('columnNameMaps'); | |
- if (isset($map['parentId'])) { | |
- $orderBy = $map['parentId'] . $orderBy; | |
- } else { | |
- $orderBy = 'parentId' . $orderBy; | |
- } | |
- // build the query this way, that the root, which has no parent (parentId=0) | |
- // and no previous (prevId=0) is in first place (in case prevId is given) | |
- $query = sprintf("SELECT * FROM %s %s ORDER BY %s", | |
- $this->table, | |
- $whereAddOn, | |
- $orderBy); //,prevId !!!! | |
- if (DB::isError($res = $this->dbh->getAll($query))) { | |
- // FIXXME remove print use debug mode instead | |
- printf("ERROR - Tree::setup - %s - %s<br>", DB::errormessage($res), $query); | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- // if the db-column names need to be mapped to different names | |
- // FIXXME somehow we should be able to do this in the query, but i dont know how to select | |
- // only those columns, use "as" on them and select the rest, without getting those columns again :-( | |
- if ($map) { | |
- foreach($res as $id => $aResult) { // map each result | |
- foreach($map as $key => $columnName) { | |
- $res[$id][$key] = $res[$id][$columnName]; | |
- unset($res[$id][$columnName]); | |
- } | |
- } | |
- } | |
- | |
- return $res; | |
- } | |
- | |
- // }}} | |
- // {{{ add() | |
- | |
- /** | |
- * adds _one_ new element in the tree under the given parent | |
- * the values' keys given have to match the db-columns, because the | |
- * value gets inserted in the db directly | |
- * to add an entire node containing children and so on see 'addNode()' | |
- * | |
- * to ba compatible, to the DBnested u can also give the parent and previd as the second and third parameter | |
- * | |
- * @see addNode | |
- * @version 2001/10/09 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array $newValues this array contains the values that shall be inserted in the db-table | |
- * the key for each element is the name of the column | |
- * @return mixed either boolean false on failure or the id of the inserted row | |
- */ | |
- function add($newValues, $parentId = 0) | |
- { | |
- // FIXXME use $this->dbh->tableInfo to check which columns exist | |
- // so only data for which a column exist is inserted | |
- if ($parentId) { | |
- $newValues['parentId'] = $parentId; | |
- } | |
- $newData = array(); | |
- foreach($newValues as $key => $value) { // quote the values, as needed for the insert | |
- $newData[$this->_getColName($key)] = $this->dbh->quote($value); | |
- } | |
- // use sequences to create a new id in the db-table | |
- $nextId = $this->dbh->nextId($this->table); | |
- $query = sprintf("INSERT INTO %s (%s,%s) VALUES (%s,%s)", | |
- $this->table , | |
- $this->_getColName('id'), | |
- implode(',', array_keys($newData)) , | |
- $nextId, | |
- implode(',', $newData)); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // TODO raise PEAR error | |
- printf("ERROR - Tree::add - %s - %s<br>", DB::errormessage($res), $query); | |
- return false; | |
- } | |
- | |
- return $nextId; | |
- } | |
- | |
- // }}} | |
- // {{{ remove() | |
- | |
- /** | |
- * removes the given node | |
- * | |
- * @version 2001/10/09 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param mixed $id the id of the node to be removed, or an array of id's to be removed | |
- * @return boolean true on success | |
- */ | |
- function remove($id) | |
- { | |
- // if the one to remove has children, get their id's to remove them too | |
- if ($this->hasChildren($id)) { | |
- $id = $this->walk(array('_remove', $this), $id, 'array'); | |
- } | |
- $idColumnName = 'id'; | |
- $map = $this->getOption('columnNameMaps'); | |
- if (isset($map['id'])) { // if there are maps given | |
- $idColumnName = $map['id']; | |
- } | |
- | |
- $whereClause = "WHERE $idColumnName=$id"; | |
- if (is_array($id)) { | |
- $whereClause = "WHERE $idColumnName in (" . implode(',', $id) . ')'; | |
- } | |
- | |
- $query = "DELETE FROM {$this->table} $whereClause"; | |
- // print("<br>".$query); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // TODO raise PEAR error | |
- printf("ERROR - Tree::remove - %s - %s<br>", DB::errormessage($res), $query); | |
- return false; | |
- } | |
- // TODO if remove succeeded set prevId of the following element properly | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ move() | |
- | |
- /** | |
- * move an entry under a given parent or behind a given entry | |
- * | |
- * @version 2001/10/10 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer $idToMove the id of the element that shall be moved | |
- * @param integer $newParentId the id of the element which will be the new parent | |
- * @param integer $newPrevId if prevId is given the element with the id idToMove | |
- * shall be moved _behind_ the element with id=prevId | |
- * if it is 0 it will be put at the beginning | |
- * if no prevId is in the DB it can be 0 too and won't bother | |
- * since it is not written in the DB anyway | |
- * @return boolean true for success | |
- */ | |
- function move($idToMove, $newParentId, $newPrevId = 0) | |
- { | |
- $idColumnName = 'id'; | |
- $parentIdColumnName = 'parentId'; | |
- $map = $this->getOption('columnNameMaps'); | |
- if (isset($map['id'])) { | |
- $idColumnName = $map['id']; | |
- } | |
- if (isset($map['parentId'])) { | |
- $parentIdColumnName = $map['parentId']; | |
- } | |
- // FIXXME todo: previous stuff | |
- // set the parent in the DB | |
- $query = "UPDATE $this->table SET $parentIdColumnName=$newParentId WHERE $idColumnName=$idToMove"; | |
- // print($query); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // TODO raise PEAR error | |
- printf("ERROR - Tree::move - %s - %s<br>", DB::errormessage($res), $query); | |
- return false; | |
- } | |
- // FIXXME update the prevId's of the elements where the element was moved away from and moved in | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ update() | |
- | |
- /** | |
- * update an element in the DB | |
- * | |
- * @version 2002/01/17 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array $newData all the new data, the key 'id' is used to | |
- * build the 'WHERE id=' clause and all the other | |
- * elements are the data to fill in the DB | |
- * @return boolean true for success | |
- */ | |
- function update($id, $newData) | |
- { | |
- // FIXXME check $this->dbh->tableInfo to see if all the columns that shall be updated | |
- // really exist, this will also extract nextId etc. if given before writing it in the DB | |
- // in case they dont exist in the DB | |
- $setData = array(); | |
- foreach($newData as $key => $value) { // quote the values, as needed for the insert | |
- $setData[] = $this->_getColName($key) . '=' . $this->dbh->quote($value); | |
- } | |
- | |
- $query = sprintf('UPDATE %s SET %s WHERE %s=%s', | |
- $this->table, | |
- implode(',', $setData), | |
- $this->_getColName('id'), | |
- $id | |
- ); | |
- if (DB::isError($res = $this->dbh->query($query))) { | |
- // FIXXME raise PEAR error | |
- printf("ERROR - Tree::update - %s - %s<br>", DB::errormessage($res), $query); | |
- return false; | |
- } | |
- | |
- return true; | |
- } | |
- | |
- // }}} | |
- // {{{ _throwError() | |
- | |
- /** | |
- * | |
- * @access private | |
- * @version 2002/03/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _throwError($msg, $line, $mode = null) | |
- { | |
- return new Tree_Error($msg, $line, __FILE__, $mode, $this->db->last_query); | |
- } | |
- | |
- // }}} | |
- // {{{ _prepareResults() | |
- | |
- /** | |
- * prepare multiple results | |
- * | |
- * @see _prepareResult | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _prepareResults($results) | |
- { | |
- $newResults = array(); | |
- foreach($results as $aResult) | |
- $newResults[] = $this->_prepareResult($aResult); | |
- return $newResults; | |
- } | |
- | |
- // }}} | |
- // {{{ _prepareResult() | |
- | |
- /** | |
- * map back the index names to get what is expected | |
- * | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _prepareResult($result) | |
- { | |
- $map = $this->getOption('columnNameMaps'); | |
- | |
- if ($map) { | |
- foreach($map as $key => $columnName) { | |
- $result[$key] = $result[$columnName]; | |
- unset($result[$columnName]); | |
- } | |
- } | |
- return $result; | |
- } | |
- | |
- // }}} | |
- // {{{ _getColName() | |
- | |
- /** | |
- * 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 <[email protected]> | |
- */ | |
- function _getColName($internalName) | |
- { | |
- if ($map = $this->getOption('columnNameMaps')) { | |
- if (isset($map[$internalName])) { | |
- return $map[$internalName]; | |
- } | |
- } | |
- return $internalName; | |
- } | |
- | |
- // }}} | |
-} | |
\ No newline at end of file | |
Index: Tree/Memory/MDBnested.php | |
=================================================================== | |
--- Tree/Memory/MDBnested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory/MDBnested.php (.../trunk) (revision 321102) | |
@@ -1,76 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/Dynamic/MDBnested.php'; | |
- | |
-/** | |
-* | |
-* | |
-* @access public | |
-* @author | |
-* @package Tree | |
-*/ | |
-class Tree_Memory_MDBnested extends Tree_Dynamic_MDBnested | |
-{ | |
- | |
- /** | |
- * retreive all the data from the db and prepare the data so the structure | |
- * can be built in the parent class | |
- * | |
- * @version 2002/04/20 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array the result of a query which retreives (all) | |
- * the tree data from a DB | |
- * @return array the result | |
- */ | |
- function setup($res = null) | |
- { | |
- if ($res == null) { | |
- // | |
- $whereAddOn = ''; | |
- if ($this->options['whereAddOn']) { | |
- $whereAddOn = 'WHERE '.$this->getOption('whereAddOn'); | |
- } | |
- | |
- // | |
- $orderBy = 'left'; | |
- if ($order=$this->getOption('order')) { | |
- $orderBy = $order; | |
- } | |
- | |
- // build the query this way, that the root, which has no parent | |
- // (parentId=0) is first | |
- $query = sprintf('SELECT * FROM %s %s ORDER BY %s', | |
- $this->table, | |
- $whereAddOn, | |
- // sort by the left-column, so we have the data | |
- //sorted as it is supposed to be :-) | |
- $this->_getColName($orderBy) | |
- ); | |
- if (MDB::isError($res = $this->dbh->getAll($query))) { | |
- return $this->_throwError($res->getMessage(), __LINE__); | |
- } | |
- } | |
- | |
- return $this->_prepareResults($res); | |
- } | |
- | |
-} | |
\ No newline at end of file | |
Index: Tree/Memory/MDB2nested.php | |
=================================================================== | |
--- Tree/Memory/MDB2nested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory/MDB2nested.php (.../trunk) (revision 321102) | |
@@ -1,76 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/Dynamic/MDB2nested.php'; | |
- | |
-/** | |
-* | |
-* | |
-* @access public | |
-* @author | |
-* @package Tree | |
-*/ | |
-class Tree_Memory_MDB2nested extends Tree_Dynamic_MDB2nested | |
-{ | |
- | |
- /** | |
- * retreive all the data from the db and prepare the data so the structure | |
- * can be built in the parent class | |
- * | |
- * @version 2002/04/20 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array the result of a query which retreives (all) | |
- * the tree data from a DB | |
- * @return array the result | |
- */ | |
- function setup($res = null) | |
- { | |
- if ($res == null) { | |
- // | |
- $whereAddOn = ''; | |
- if ($this->options['whereAddOn']) { | |
- $whereAddOn = 'WHERE '.$this->getOption('whereAddOn'); | |
- } | |
- | |
- // | |
- $orderBy = 'left'; | |
- if ($order = $this->getOption('order')) { | |
- $orderBy = $order; | |
- } | |
- | |
- // build the query this way, that the root, which has no parent | |
- // (parentId=0) is first | |
- $query = sprintf('SELECT * FROM %s %s ORDER BY %s', | |
- $this->table, | |
- $whereAddOn, | |
- // sort by the left-column, so we have the data | |
- //sorted as it is supposed to be :-) | |
- $this->_getColName($orderBy) | |
- ); | |
- if (MDB2::isError($res = $this->dbh->queryAll($query))) { | |
- return Tree::raiseError('TREE_ERROR_DB_ERROR', $res->getMessage()); | |
- } | |
- } | |
- | |
- return $this->_prepareResults($res); | |
- } | |
- | |
-} | |
\ No newline at end of file | |
Index: Tree/Memory/DBnested.php | |
=================================================================== | |
--- Tree/Memory/DBnested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory/DBnested.php (.../trunk) (revision 321102) | |
@@ -1,76 +0,0 @@ | |
-<?php | |
-/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
-// +----------------------------------------------------------------------+ | |
-// | PHP Version 4 | | |
-// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
-// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
-// | that is bundled with this package in the file LICENSE, and is | | |
-// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
-// | If you did not receive a copy of the PHP license and are unable to | | |
-// | obtain it through the world-wide-web, please send a note to | | |
-// | [email protected] so we can mail you a copy immediately. | | |
-// +----------------------------------------------------------------------+ | |
-// | Authors: | | |
-// +----------------------------------------------------------------------+ | |
-// | |
-// $Id$ | |
- | |
-require_once 'Tree/Dynamic/DBnested.php'; | |
- | |
-/** | |
- * | |
- * | |
- * @access public | |
- * @author | |
- * @package Tree | |
- */ | |
-class Tree_Memory_DBnested extends Tree_Dynamic_DBnested | |
-{ | |
- | |
- /** | |
- * retreive all the data from the db and prepare the data so the structure | |
- * can be built in the parent class | |
- * | |
- * @version 2002/04/20 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param array the result of a query which retreives (all) | |
- * the tree data from a DB | |
- * @return array the result | |
- */ | |
- function setup($res = null) | |
- { | |
- if ($res == null) { | |
- // | |
- $whereAddOn = ''; | |
- if ($this->options['whereAddOn']) { | |
- $whereAddOn = 'WHERE '.$this->getOption('whereAddOn'); | |
- } | |
- | |
- // | |
- $orderBy = 'left'; | |
- if ($order = $this->getOption('order')) { | |
- $orderBy = $order; | |
- } | |
- | |
- // build the query this way, that the root, which has no parent | |
- // (parentId=0) is first | |
- $query = sprintf('SELECT * FROM %s %s ORDER BY %s', | |
- $this->table, | |
- $whereAddOn, | |
- // sort by the left-column, so we have the data | |
- //sorted as it is supposed to be :-) | |
- $this->_getColName($orderBy) | |
- ); | |
- if (DB::isError($res = $this->dbh->getAll($query))) { | |
- return $this->_throwError($res->getMessage(),__LINE__); | |
- } | |
- } | |
- | |
- return $this->_prepareResults( $res ); | |
- } | |
- | |
-} | |
\ No newline at end of file | |
Index: Tree/Memory/SQLsimple.php | |
=================================================================== | |
--- Tree/Memory/SQLsimple.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Memory/SQLsimple.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,264 @@ | |
+<?php | |
+ | |
+// +----------------------------------------------------------------------+ | |
+// | PHP Version 4 | | |
+// +----------------------------------------------------------------------+ | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
+// +----------------------------------------------------------------------+ | |
+// | This source file is subject to version 2.02 of the PHP license, | | |
+// | that is bundled with this package in the file LICENSE, and is | | |
+// | available at through the world-wide-web at | | |
+// | http://www.php.net/license/2_02.txt. | | |
+// | If you did not receive a copy of the PHP license and are unable to | | |
+// | obtain it through the world-wide-web, please send a note to | | |
+// | [email protected] so we can mail you a copy immediately. | | |
+// +----------------------------------------------------------------------+ | |
+// | Authors: Wolfram Kriesing <[email protected]> | | |
+// | Lorenzo Alberton <[email protected]> | | |
+// | Helgi Þormar Þorbjörnsson <[email protected]> | | |
+// +----------------------------------------------------------------------+ | |
+ | |
+// $Id$ | |
+ | |
+require_once 'Tree/Memory.php'; | |
+ | |
+/** | |
+* the SQL interface to the tree class | |
+* | |
+* @access public | |
+* @author Wolfram Kriesing <[email protected]> | |
+* @author Helgi Þormar Þorbjörnsson <[email protected]> | |
+* @author Lorenzo Alberton <[email protected]> | |
+* @package Tree | |
+*/ | |
+class Tree_Memory_SQLsimple extends Tree_Memory | |
+{ | |
+ // {{{ Tree_Memory_MDBsimple() | |
+ | |
+ /** | |
+ * set up this object | |
+ * | |
+ * @access public | |
+ * @param string $dsn this is a DSN of the for that PEAR::DB uses it | |
+ * only that additionally you can add parameters like ...?table=test_table | |
+ * to define the table it shall work on | |
+ * @param array $options additional options you can set | |
+ */ | |
+ function Tree_Memory_SQLsimple($config) | |
+ { | |
+ $this->_construct($config); | |
+ } | |
+ | |
+ function __construct($config) | |
+ { | |
+ $this->conf = Tree::arrayMergeClobber($this->conf, $config['options']); | |
+ $this->init($config); | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ setup() | |
+ | |
+ /** | |
+ * retrieve all the navigation data from the db and call build to build the | |
+ * tree in the array data and structure | |
+ * | |
+ * @access public | |
+ * @return boolean true on success | |
+ */ | |
+ function setup() | |
+ { | |
+ // TODO sort by prevId (parent_id, prevId $addQuery) too if it exists in the table, | |
+ // or the root might be wrong, since the prevId of the root should be 0 | |
+ | |
+ $where = $this->conf['whereAddOn'] | |
+ ? 'WHERE ' . $this->conf['whereAddOn'] : ''; | |
+ | |
+ $order = $this->conf['order'] ? ',' . $this->conf['order'] : ''; | |
+ | |
+ $order = $this->conf['fields']['parent_id']['name'] . $order; | |
+ | |
+ // build the query this way, that the root, which has no parent (parent_id=0) | |
+ // and no previous (prevId=0) is in first place (in case prevId is given) | |
+ $query = sprintf("SELECT * FROM %s %s ORDER BY %s", | |
+ $this->conf['table'], | |
+ $where, | |
+ $order); //,prevId !!!! | |
+ $res = $this->_storage->queryAll($query, array(), false, false); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ // if the db-column names need to be mapped to different names | |
+ // FIXXME somehow we should be able to do this in the query, but I dont know | |
+ // how to select only those columns, use "as" on them and select the rest, | |
+ //without getting those columns again :-( | |
+ $res = $this->_prepareResults($res); | |
+ | |
+ return $res; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ add() | |
+ | |
+ /** | |
+ * adds _one_ new element in the tree under the given parent | |
+ * the values' keys given have to match the db-columns, because the | |
+ * value gets inserted in the db directly | |
+ * to add an entire node containing children and so on see 'addNode()' | |
+ * | |
+ * to be compatible with the MDBnested, u can also give the parent and previd | |
+ * as the second and third parameter | |
+ * | |
+ * @see addNode | |
+ * @access public | |
+ * @param array $newValues this array contains the values that shall be inserted in the db-table | |
+ * the key for each element is the name of the column | |
+ * @return mixed either boolean false on failure or the id of the inserted row | |
+ */ | |
+ function add($data, $parent_id = 0) | |
+ { | |
+ // FIXXME use $this->dbc->tableInfo to check which columns exist | |
+ // so only data for which a column exist is inserted | |
+ if ($parent_id) { | |
+ $data['parent_id'] = $parent_id; | |
+ } | |
+ | |
+ $newData = array(); | |
+ foreach ($data as $key => $value) { | |
+ // quote the values, as needed for the insert | |
+ $type = $this->conf['fields'][$key]['type']; | |
+ $name = $this->_getColName($key); | |
+ $newData[$name] = $this->_storage->quote($value, $type); | |
+ } | |
+ | |
+ // use sequences to create a new id in the db-table | |
+ $id = $this->_storage->nextId($this->conf['table']); | |
+ if (PEAR::isError($id)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $id->getMessage() . '-' . $id->getUserInfo()); | |
+ } | |
+ | |
+ $query = sprintf("INSERT INTO %s (%s, %s) VALUES (%s, %s)", | |
+ $this->conf['table'] , | |
+ $this->_getColName('id'), | |
+ implode(', ', array_keys($newData)) , | |
+ $id, | |
+ implode(', ', $newData)); | |
+ $result = $this->_storage->query($query); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ | |
+ return $id; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ remove() | |
+ | |
+ /** | |
+ * removes the given node | |
+ * | |
+ * @access public | |
+ * @param mixed $id the id of the node to be removed, or an array of id's to be removed | |
+ * @return boolean true on success | |
+ */ | |
+ function remove($id) | |
+ { | |
+ // if the one to remove has children, get their id's to remove them too | |
+ if ($this->hasChildren($id)) { | |
+ $id = $this->walk(array('_remove', $this), $id, 'array'); | |
+ } else { | |
+ $id = array($id); | |
+ } | |
+ | |
+ $where = " | |
+ WHERE {$this->conf['fields']['id']['name']} | |
+ IN (" . implode(', ', $id) . ')'; | |
+ | |
+ $query = 'DELETE FROM ' . $this->conf['table'] . $where; | |
+ $result = $this->_storage->query($query); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ | |
+ // TODO if remove succeeded set prevId of the following element properly | |
+ return true; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ move() | |
+ | |
+ /** | |
+ * move an entry under a given parent or behind a given entry | |
+ * | |
+ * @version 2001/10/10 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer $idToMove the id of the element that shall be moved | |
+ * @param integer $newparent_id the id of the element which will be the new parent | |
+ * @param integer $newPrevId if prevId is given the element with the id idToMove | |
+ * shall be moved _behind_ the element with id=prevId | |
+ * if it is 0 it will be put at the beginning | |
+ * if no prevId is in the DB it can be 0 too and won't bother | |
+ * since it is not written in the DB anyway | |
+ * @return boolean true for success | |
+ */ | |
+ function move($idToMove, $newParent, $newPrevId = 0) | |
+ { | |
+ $idName = $this->conf['fields']['id']['name']; | |
+ $parentName = $this->conf['fields']['parent_id']['name']; | |
+ | |
+ // FIXXME todo: previous stuff | |
+ // set the parent in the DB | |
+ $query = " | |
+ UPDATE {$this->conf['table']} SET | |
+ $parentName = $newParent | |
+ WHERE $idName = $idToMove"; | |
+ $result = $this->_storage->query($query); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ // FIXXME update the prevId's of the elements where the element was moved away from and moved in | |
+ return true; | |
+ } | |
+ | |
+ // }}} | |
+ // {{{ update() | |
+ | |
+ /** | |
+ * update an element in the DB | |
+ * | |
+ * @version 2002/01/17 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param array $newData all the new data, the key 'id' is used to | |
+ build the 'WHERE id=' clause and all the other | |
+ * elements are the data to fill in the DB | |
+ * @return boolean true for success | |
+ */ | |
+ function update($id, $data) | |
+ { | |
+ // FIXXME check $this->dbc->tableInfo to see if all the columns that shall be updated | |
+ // really exist, this will also extract nextId etc. if given before writing it in the DB | |
+ // in case they dont exist in the DB | |
+ $setData = array(); | |
+ foreach ($data as $key => $value) { // quote the values, as needed for the insert | |
+ $type = $this->conf['fields'][$key]['type']; | |
+ $setData[] = $this->_getColName($key) . ' = ' . $this->_storage->quote($value, $type); | |
+ } | |
+ | |
+ $query = sprintf('UPDATE %s SET %s WHERE %s = %s', | |
+ $this->conf['table'], | |
+ implode(',', $setData), | |
+ $this->_getColName('id'), | |
+ $id | |
+ ); | |
+ $result = $this->_storage->query($query); | |
+ if (PEAR::isError($result)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $result->getMessage() . '-' . $result->getUserInfo()); | |
+ } | |
+ | |
+ return true; | |
+ } | |
+ | |
+ // }}} | |
+} | |
+?> | |
\ No newline at end of file | |
Property changes on: Tree/Memory/SQLsimple.php | |
___________________________________________________________________ | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Index: Tree/Memory/Simple.php | |
=================================================================== | |
--- Tree/Memory/Simple.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Memory/Simple.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,62 @@ | |
+<?php | |
+/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
+// +----------------------------------------------------------------------+ | |
+// | PHP Version 4 | | |
+// +----------------------------------------------------------------------+ | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
+// +----------------------------------------------------------------------+ | |
+// | This source file is subject to version 3.0 of the PHP license, | | |
+// | that is bundled with this package in the file LICENSE, and is | | |
+// | available at through the world-wide-web at | | |
+// | http://www.php.net/license/3_0.txt. | | |
+// | If you did not receive a copy of the PHP license and are unable to | | |
+// | obtain it through the world-wide-web, please send a note to | | |
+// | [email protected] so we can mail you a copy immediately. | | |
+// +----------------------------------------------------------------------+ | |
+// | Authors: | | |
+// +----------------------------------------------------------------------+ | |
+// | |
+// $Id$ | |
+ | |
+require_once 'Tree/Memory.php'; | |
+ | |
+class Tree_Memory_Simple extends Tree_Memory { | |
+ | |
+ function setup() | |
+ { | |
+ $this->_storage->select(); | |
+ } | |
+ | |
+ function add($data, $parentId = 0) | |
+ { | |
+ $this->_storage->insert(); | |
+ } | |
+ | |
+ function remove($id) | |
+ { | |
+ // if the one to remove has children, get their id's to remove them too | |
+ if ($this->hasChildren($id)) { | |
+ $id = $this->walk(array('_remove', $this), $id, 'array'); | |
+ } else { | |
+ $id = array($id); | |
+ } | |
+ | |
+ $result = $this->_storage->remove(); | |
+ if (PEAR::isError($result)) { | |
+ return $result; | |
+ } | |
+ | |
+ return true; | |
+ } | |
+ | |
+ function update($id, $data) | |
+ { | |
+ $this->_storage->update(); | |
+ } | |
+ | |
+ function move($idToMove, $newParent, $newPrevId = 0) | |
+ { | |
+ $this->_storage->update(); | |
+ } | |
+} | |
+?> | |
\ No newline at end of file | |
Property changes on: Tree/Memory/Simple.php | |
___________________________________________________________________ | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Index: Tree/Memory/Array.php | |
=================================================================== | |
--- Tree/Memory/Array.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory/Array.php (.../trunk) (revision 321102) | |
@@ -3,12 +3,12 @@ | |
// +----------------------------------------------------------------------+ | |
// | PHP Version 4 | | |
// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
+// | This source file is subject to version 3.0 of the PHP license, | | |
// | that is bundled with this package in the file LICENSE, and is | | |
// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
+// | http://www.php.net/license/3_0.txt. | | |
// | If you did not receive a copy of the PHP license and are unable to | | |
// | obtain it through the world-wide-web, please send a note to | | |
// | [email protected] so we can mail you a copy immediately. | | |
@@ -18,8 +18,6 @@ | |
// | |
// $Id$ | |
-require_once 'Tree/Error.php'; | |
- | |
/** | |
* EXPERIMENTAL | |
* | |
@@ -86,7 +84,7 @@ | |
* so methods like 'add' etc can find the elements they are searching for, | |
* if you dont like your data to be modified dont pass them as reference! | |
*/ | |
- function _setup(&$array, $parentId = 0) | |
+ function _setup(&$array, $parent_id = 0) | |
{ | |
foreach ($array as $nodeKey => $aNode) { | |
$newData = $aNode; | |
@@ -103,7 +101,7 @@ | |
} | |
} | |
// set the parent-id, since we only have a 'children' array | |
- $newData['parentId'] = $parentId; | |
+ $newData['parent_id'] = $parent_id; | |
$children = null; | |
// remove the 'children' array, since this is only info for | |
// this class | |
@@ -138,59 +136,16 @@ | |
foreach ($data as $aNode) { | |
foreach ($aNode as $key => $val) { | |
- if (is_array($val) || in_array($key,$unsetKeys)) { | |
+ if (is_array($val) || in_array($key, $unsetKeys)) { | |
unset($aNode[$key]); | |
} | |
} | |
- $this->add($aNode,$aNode['parentId']); | |
+ $this->add($aNode,$aNode['parent_id']); | |
} | |
$this->_array = $this->_array['children'][0]; | |
} | |
// }}} | |
- // {{{ _prepareResults() | |
- | |
- /** | |
- * prepare multiple results | |
- * | |
- * @see _prepareResult() | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _prepareResults($results) | |
- { | |
- $newResults = array(); | |
- foreach($results as $aResult) { | |
- $newResults[] = $this->_prepareResult($aResult); | |
- } | |
- return $newResults; | |
- } | |
- | |
- // }}} | |
- // {{{ _prepareResult() | |
- | |
- /** | |
- * map back the index names to get what is expected | |
- * | |
- * @access private | |
- * @version 2002/03/03 | |
- * @author Wolfram Kriesing <[email protected]> | |
- */ | |
- function _prepareResult($result) | |
- { | |
- $map = $this->getOption('columnNameMaps'); | |
- | |
- if ($map) { | |
- foreach($map as $key => $columnName) { | |
- $result[$key] = $result[$columnName]; | |
- unset($result[$columnName]); | |
- } | |
- } | |
- return $result; | |
- } | |
- | |
- // }}} | |
// {{{ add() | |
/** | |
@@ -201,7 +156,7 @@ | |
* @param int the ID of the parent node | |
* @param int the ID of the previous node | |
*/ | |
- function add($data, $parentId, $previousId = null) | |
+ function add($data, $parent_id, $previousId = null) | |
{ | |
if (!isset($data['id'])) { | |
$data['id'] = ++$this->_id; | |
@@ -210,17 +165,17 @@ | |
// the $this->_id if the data['id'] has a higher number. | |
$this->_id = (int)$data['id']; | |
} | |
- $data['parentId'] = $parentId; | |
+ $data['parent_id'] = $parent_id; | |
$this->data[$data['id']] = $data; | |
// there might not be a root element yet | |
if (!isset($this->_array['children'])) { | |
- $data['parentId'] = 0; | |
+ $data['parent_id'] = 0; | |
$this->_array['children'][] = $data; | |
} else { | |
array_walk($this->_array['children'], | |
- array(&$this,'_add'), | |
- array($data,$parentId,$previousId) | |
+ array(&$this, '_add'), | |
+ array($data, $parent_id, $previousId) | |
); | |
} | |
return $data['id']; | |
@@ -244,7 +199,7 @@ | |
*/ | |
function _add(&$val, $key, $data) | |
{ | |
- // is the id of the current elment ($val) == to the parentId ($data[1]) | |
+ // is the id of the current elment ($val) == to the parent_id ($data[1]) | |
if ($val['id'] == $data[1]) { | |
if (isset($data[2]) && $data[2] === 0) { | |
// if the previousId is 0 means, add it as the first member | |
@@ -254,7 +209,7 @@ | |
} | |
} else { // if we havent found the new element go on searching | |
if (isset($val['children'])) { | |
- array_walk($val['children'],array(&$this,'_add'),$data); | |
+ array_walk($val['children'],array(&$this, '_add'), $data); | |
} | |
} | |
} | |
@@ -270,16 +225,16 @@ | |
* @param array the data, [key]=>[value] | |
* @return void | |
*/ | |
- function update($id,$data) | |
+ function update($id, $data) | |
{ | |
- if ($this->_array['id']==$id) { | |
- foreach ($data as $key=>$newVal) { | |
+ if ($this->_array['id'] == $id) { | |
+ foreach ($data as $key => $newVal) { | |
$this->_array[$key] = $newVal; | |
} | |
} else { | |
array_walk($this->_array['children'], | |
- array(&$this,'_update'), | |
- array($id,$data) | |
+ array(&$this, '_update'), | |
+ array($id, $data) | |
); | |
} | |
} | |
@@ -300,7 +255,7 @@ | |
*/ | |
function _update(&$val, $key, $data) | |
{ | |
- // is the id of the current elment ($val) == to the parentId ($data[1]) | |
+ // is the id of the current elment ($val) == to the parent_id ($data[1]) | |
if ($val['id'] == $data[0]) { | |
foreach ($data[1] as $key => $newVal) { | |
$val[$key] = $newVal; | |
@@ -309,7 +264,7 @@ | |
// if we havent found the new element go on searching | |
// in the children | |
if (isset($val['children'])) { | |
- array_walk($val['children'],array(&$this,'_update'), $data); | |
+ array_walk($val['children'],array(&$this, '_update'), $data); | |
} | |
} | |
} | |
@@ -328,7 +283,7 @@ | |
// we only need to search for element that do exist :-) | |
// otherwise we save some processing time | |
if ($this->data[$id]) { | |
- $this->_remove($this->_array,$id); | |
+ $this->_remove($this->_array, $id); | |
} | |
} | |
@@ -350,17 +305,18 @@ | |
if (isset($val['children'])) { | |
foreach ($val['children'] as $key => $aVal) { | |
if ($aVal['id'] == $id) { | |
- if (sizeof($val['children']) < 2) { | |
+ if (count($val['children']) < 2) { | |
unset($val['children']); | |
} else { | |
unset($val['children'][$key]); | |
} | |
} else { | |
- $this->_remove($val['children'][$key],$id); | |
+ $this->_remove($val['children'][$key], $id); | |
} | |
} | |
} | |
} | |
// }}} | |
-} | |
\ No newline at end of file | |
+} | |
+?> | |
\ No newline at end of file | |
Property changes on: Tree/Memory/Array.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.14.2.2 | |
+1.15 | |
Index: Tree/Memory/XML.php | |
=================================================================== | |
--- Tree/Memory/XML.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory/XML.php (.../trunk) (revision 321102) | |
@@ -3,12 +3,12 @@ | |
// +----------------------------------------------------------------------+ | |
// | PHP Version 4 | | |
// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
// +----------------------------------------------------------------------+ | |
-// | This source file is subject to version 2.02 of the PHP license, | | |
+// | This source file is subject to version 3.0 of the PHP license, | | |
// | that is bundled with this package in the file LICENSE, and is | | |
// | available at through the world-wide-web at | | |
-// | http://www.php.net/license/2_02.txt. | | |
+// | http://www.php.net/license/3_0.txt. | | |
// | If you did not receive a copy of the PHP license and are unable to | | |
// | obtain it through the world-wide-web, please send a note to | | |
// | [email protected] so we can mail you a copy immediately. | | |
@@ -30,7 +30,6 @@ | |
*/ | |
class Tree_Memory_XML extends XML_Parser | |
{ | |
- | |
/** | |
* @var array the first element has to be empty, so we can use | |
* the parentId=0 as "no parent" | |
@@ -72,9 +71,9 @@ | |
* @author Wolfram Kriesing <[email protected]> | |
* @return boolean true on success | |
*/ | |
- function Tree_Memory_XML($dsn, $options) | |
+ function Tree_Memory_XML($config) | |
{ | |
- $handle = $dsn; | |
+ $handle = $config['storage']['dsn']; | |
$this->XML_Parser(); | |
@@ -100,12 +99,12 @@ | |
*/ | |
function startHandler($parser, $element, $attribs) | |
{ | |
- $elementBeforeId = sizeof($this->data) - 1; | |
- $curId = sizeof($this->data); | |
+ $elementBeforeId = count($this->data) - 1; | |
+ $curId = count($this->data); | |
$this->data[$curId]['id'] = $curId; | |
- $this->data[$curId]['name'] = $this->_toLower? | |
- strtolower($element):$element; | |
+ $this->data[$curId]['name'] = $this->_toLower ? | |
+ strtolower($element) : $element; | |
$this->data[$curId]['level'] = $this->level; | |
$this->data[$curId]['attributes'] = $attribs; | |
if ($this->_toLower) { | |
@@ -168,11 +167,11 @@ | |
# ANSWER: if you call xml_parse($parser, "foo ", false) and then | |
# xml_parse($parser, "bar", true), callbacks are done once | |
# for each xml_parse() call. | |
- if (!isset($this->data[ sizeof($this->data)-1 ]['cdata'])) { | |
- $this->data[ sizeof($this->data)-1 ]['cdata'] = ''; | |
+ if (!isset($this->data[count($this->data) - 1]['cdata'])) { | |
+ $this->data[count($this->data) - 1]['cdata'] = ''; | |
} | |
#print "cdata = '$cdata'\r\n"; | |
- $this->data[ sizeof($this->data)-1 ]['cdata'].= $cdata; | |
+ $this->data[count($this->data) - 1]['cdata'].= $cdata; | |
} | |
// }}} | |
@@ -188,7 +187,7 @@ | |
*/ | |
function defaultHandler($parser, $cdata) | |
{ | |
- // $this->data[ sizeof($this->data)-1 ]['cdata'] = $cdata; | |
+ // $this->data[ count($this->data)-1 ]['cdata'] = $cdata; | |
// not in use yet :-( is that ok?? | |
} | |
@@ -252,7 +251,7 @@ | |
/* function add($newValues) | |
{ | |
// add the data in the internal structure $this->data | |
- $this->data[sizeof($this->data)] = $newValues; | |
+ $this->data[count($this->data)] = $newValues; | |
# i am thinking if it might be a good solution to walk the data-array | |
# and write each line singlely until the one to add comes, write it and | |
@@ -312,4 +311,5 @@ | |
} | |
*/ | |
-} | |
\ No newline at end of file | |
+} | |
+?> | |
Property changes on: Tree/Memory/XML.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.11.2.1 | |
+1.12 | |
Index: Tree/Memory/SQLnested.php | |
=================================================================== | |
--- Tree/Memory/SQLnested.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Memory/SQLnested.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,78 @@ | |
+<?php | |
+/* vim: set expandtab tabstop=4 shiftwidth=4: */ | |
+// +----------------------------------------------------------------------+ | |
+// | PHP Version 4 | | |
+// +----------------------------------------------------------------------+ | |
+// | Copyright (c) 1997-2003 The PHP Group | | |
+// +----------------------------------------------------------------------+ | |
+// | This source file is subject to version 2.02 of the PHP license, | | |
+// | that is bundled with this package in the file LICENSE, and is | | |
+// | available at through the world-wide-web at | | |
+// | http://www.php.net/license/2_02.txt. | | |
+// | If you did not receive a copy of the PHP license and are unable to | | |
+// | obtain it through the world-wide-web, please send a note to | | |
+// | [email protected] so we can mail you a copy immediately. | | |
+// +----------------------------------------------------------------------+ | |
+// | Authors: | | |
+// +----------------------------------------------------------------------+ | |
+// | |
+// $Id$ | |
+ | |
+require_once 'Tree/Dynamic/SQLnested.php'; | |
+ | |
+/** | |
+ * | |
+ * | |
+ * @access public | |
+ * @author | |
+ * @package Tree | |
+ */ | |
+class Tree_Memory_SQLnested extends Tree_Dynamic_SQLnested | |
+{ | |
+ /** | |
+ * retreive all the data from the db and prepare the data so the structure | |
+ * can be built in the parent class | |
+ * | |
+ * @version 2002/04/20 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param array the result of a query which retreives (all) | |
+ * the tree data from a DB | |
+ * @return array the result | |
+ */ | |
+ function setup($res = null) | |
+ { | |
+ if ($res == null) { | |
+ // | |
+ $whereAddOn = ''; | |
+ if ($this->conf['whereAddOn']) { | |
+ $whereAddOn = 'WHERE '.$this->conf['whereAddOn']; | |
+ } | |
+ | |
+ // | |
+ $orderBy = 'left'; | |
+ if ($order = $this->conf['order']) { | |
+ $orderBy = $order; | |
+ } | |
+ | |
+ // build the query this way, that the root, which has no parent | |
+ // (parent_id=0) is first | |
+ $query = sprintf('SELECT * FROM %s %s ORDER BY %s', | |
+ $this->conf['table'], | |
+ $whereAddOn, | |
+ // sort by the left-column, so we have the data | |
+ //sorted as it is supposed to be :-) | |
+ $this->_getColName($orderBy) | |
+ ); | |
+ $res = $this->_storage->queryAll($query, array(), false, false); | |
+ if (PEAR::isError($res)) { | |
+ return Tree::raiseError(TREE_ERROR_DB_ERROR, null, null, $res->getMessage()); | |
+ } | |
+ } | |
+ | |
+ return $this->_prepareResults($res); | |
+ } | |
+ | |
+} | |
+ | |
+?> | |
\ No newline at end of file | |
Property changes on: Tree/Memory/SQLnested.php | |
___________________________________________________________________ | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Index: Tree/Memory/Filesystem.php | |
=================================================================== | |
--- Tree/Memory/Filesystem.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory/Filesystem.php (.../trunk) (revision 321102) | |
@@ -3,7 +3,7 @@ | |
// +----------------------------------------------------------------------+ | |
// | PHP Version 4 | | |
// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
// +----------------------------------------------------------------------+ | |
// | This source file is subject to version 2.02 of the PHP license, | | |
// | that is bundled with this package in the file LICENSE, and is | | |
@@ -18,8 +18,6 @@ | |
// | |
// $Id$ | |
-require_once 'Tree/Error.php'; | |
- | |
/** | |
* the Filesystem interface to the tree class | |
* this is a bit different, as id we use the entire path, since we know | |
@@ -35,6 +33,9 @@ | |
* I also thought about hashing the path name but then the add method is | |
* not that easy to implement ... may be one day :-) | |
* | |
+ * Use the System class | |
+ * http://cvs.php.net/pear-core/System.php | |
+ * | |
* @access public | |
* @author Wolfram Kriesing <[email protected]> | |
* @version 2001/06/27 | |
@@ -47,9 +48,9 @@ | |
* @access public | |
* @var array saves the options passed to the constructor | |
*/ | |
- var $options = array( | |
+ var $conf = array( | |
'order' => '', | |
- 'columnNameMaps' => array(), | |
+ 'fields' => array(), | |
); | |
// {{{ Tree_Memory_Filesystem() | |
@@ -63,7 +64,7 @@ | |
* @param string $dsn the path on the filesystem | |
* @param array $options additional options you can set | |
*/ | |
- function Tree_Memory_Filesystem ($path, $options = array()) | |
+ function Tree_Memory_Filesystem($path, $options = array()) | |
{ | |
$this->_path = $path; | |
// not in use currently | |
@@ -135,8 +136,7 @@ | |
# FIXXME do the mapping | |
if (!@mkdir("$parent/{$newValues['name']}", 0700)) { | |
return $this->_raiseError(TREE_ERROR_CANNOT_CREATE_FOLDER, | |
- $newValues['name'].' under '.$parent, | |
- __LINE__ | |
+ $newValues['name'].' under '.$parent | |
); | |
} | |
return "$parent/{$newValues['name']}"; | |
@@ -206,7 +206,7 @@ | |
*/ | |
function _prepareResult($result) | |
{ | |
- $map = $this->getOption('columnNameMaps'); | |
+ $map = $this->getOption('fields'); | |
if ($map) { | |
foreach ($map as $key => $columnName) { | |
$result[$key] = $result[$columnName]; | |
@@ -217,4 +217,5 @@ | |
} | |
// }}} | |
-} | |
\ No newline at end of file | |
+} | |
+?> | |
\ No newline at end of file | |
Property changes on: Tree/Memory/Filesystem.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.9.2.2 | |
+1.10 | |
Index: Tree/Storage.php | |
=================================================================== | |
--- Tree/Storage.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ Tree/Storage.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,102 @@ | |
+<?php | |
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ | |
+ | |
+/** | |
+ * A framework for authentication and authorization in PHP applications | |
+ * | |
+ * LiveUser_Admin is meant to be used with the LiveUser package. | |
+ * It is composed of all the classes necessary to administrate | |
+ * data used by LiveUser. | |
+ * | |
+ * You'll be able to add/edit/delete/get things like: | |
+ * * Rights | |
+ * * Users | |
+ * * Groups | |
+ * * Areas | |
+ * * Applications | |
+ * * Subgroups | |
+ * * ImpliedRights | |
+ * | |
+ * And all other entities within LiveUser. | |
+ * | |
+ * At the moment we support the following storage containers: | |
+ * * DB | |
+ * * MDB | |
+ * * MDB2 | |
+ * | |
+ * But it takes no time to write up your own storage container, | |
+ * so if you like to use native mysql functions straight, then it's possible | |
+ * to do so in under a hour! | |
+ * | |
+ * PHP version 4 and 5 | |
+ * | |
+ * LICENSE: This library is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU Lesser General Public | |
+ * License as published by the Free Software Foundation; either | |
+ * version 2.1 of the License, or (at your option) any later version. | |
+ * | |
+ * This library is distributed in the hope that it will be useful, | |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
+ * Lesser General Public License for more details. | |
+ * | |
+ * You should have received a copy of the GNU Lesser General Public | |
+ * License along with this library; if not, write to the Free Software | |
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
+ * MA 02111-1307 USA | |
+ * | |
+ * | |
+ * @category authentication | |
+ * @package LiveUser_Admin | |
+ * @author Markus Wolff <[email protected]> | |
+ * @author Helgi Þormar Þorbjörnsson <[email protected]> | |
+ * @author Lukas Smith <[email protected]> | |
+ * @author Arnaud Limbourg <[email protected]> | |
+ * @author Christian Dickmann <[email protected]> | |
+ * @author Matt Scifo <[email protected]> | |
+ * @author Bjoern Kraus <[email protected]> | |
+ * @copyright 2002-2005 Markus Wolff | |
+ * @license http://www.gnu.org/licenses/lgpl.txt | |
+ * @version CVS: $Id$ | |
+ * @link http://pear.php.net/LiveUser_Admin | |
+ */ | |
+ | |
+/** | |
+ * This is a PEAR::MDB2 backend driver for the LiveUser class. | |
+ * A PEAR::MDB2 connection object can be passed to the constructor to reuse an | |
+ * existing connection. Alternatively, a DSN can be passed to open a new one. | |
+ * | |
+ * Requirements: | |
+ * - File "Liveuser.php" (contains the parent class "LiveUser") | |
+ * - Array of connection options or a PEAR::MDB2 connection object must be | |
+ * passed to the constructor. | |
+ * Example: array('dsn' => 'mysql://user:pass@host/db_name') | |
+ * OR | |
+ * &$conn (PEAR::MDB2 connection object) | |
+ * | |
+ * @category authentication | |
+ * @package LiveUser_Admin | |
+ * @author Lukas Smith <[email protected]> | |
+ * @author Bjoern Kraus <[email protected]> | |
+ * @copyright 2002-2005 Markus Wolff | |
+ * @license http://www.gnu.org/licenses/lgpl.txt | |
+ * @version Release: @package_version@ | |
+ * @link http://pear.php.net/LiveUser_Admin | |
+ */ | |
+class Tree_Storage | |
+{ | |
+ function init(&$storageConf) | |
+ { | |
+ return true; | |
+ } | |
+ | |
+ /** | |
+ * properly disconnect from resources | |
+ * | |
+ * @access public | |
+ */ | |
+ function disconnect() | |
+ { | |
+ } | |
+} | |
+?> | |
Property changes on: Tree/Storage.php | |
___________________________________________________________________ | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Index: Tree/Memory.php | |
=================================================================== | |
--- Tree/Memory.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ Tree/Memory.php (.../trunk) (revision 321102) | |
@@ -3,7 +3,7 @@ | |
// +----------------------------------------------------------------------+ | |
// | PHP Version 4 | | |
// +----------------------------------------------------------------------+ | |
-// | Copyright (c) 1997-2003 The PHP Group | | |
+// | Copyright (c) 1997-2005 The PHP Group | | |
// +----------------------------------------------------------------------+ | |
// | This source file is subject to version 2.02 of the PHP license, | | |
// | that is bundled with this package in the file LICENSE, and is | | |
@@ -18,7 +18,7 @@ | |
// | |
// $Id$ | |
-require_once 'Tree/Common.php'; | |
+require_once 'Tree/Tree.php'; | |
/** | |
* this class can be used to step through a tree using ['parent'],['child'] | |
@@ -42,7 +42,7 @@ | |
* +---level 1_2 (5) | |
* | |
* the database table to this structure (without defined order) | |
- * id parentId name | |
+ * id parent_id name | |
* 1 0 level 1_1 | |
* 2 1 level 2_1 | |
* 3 1 level 2_1 | |
@@ -87,7 +87,7 @@ | |
* @version 2001/06/27 | |
* @package Tree | |
*/ | |
-class Tree_Memory extends Tree_Common | |
+class Tree_Memory extends Tree | |
{ | |
/** | |
* this array contains the pure data from the DB | |
@@ -112,7 +112,7 @@ | |
var $structure = array(); | |
/** | |
- * it contains all the parents and their children, where the parentId is the | |
+ * it contains all the parents and their children, where the parent_id is the | |
* key and all the children are the values, this is for speeding up | |
* the tree-building process | |
* | |
@@ -121,22 +121,6 @@ | |
var $children = array(); | |
/** | |
- * @access private | |
- * @var boolean saves if tree nodes shall be removed recursively | |
- * @see setRemoveRecursively() | |
- */ | |
- var $removeRecursively = false; | |
- | |
- | |
- /** | |
- * @access public | |
- * @var integer the debug mode, if > 0 then debug info are shown, | |
- * actually those messages only show performance | |
- * times | |
- */ | |
- var $debug = 0; | |
- | |
- /** | |
* @see &getNode() | |
* @see &_getNode() | |
* @access private | |
@@ -160,6 +144,8 @@ | |
*/ | |
var $_treeDepth = 0; | |
+ var $walkReturn = array(); | |
+ | |
// {{{ Tree_Memory() | |
/** | |
@@ -172,24 +158,33 @@ | |
* either an object/string | |
* @param array additional options you can set | |
*/ | |
- function Tree_Memory($type, $dsn = '', $options = array()) | |
+ function Tree_Memory($config) | |
{ | |
- // set the options for $this | |
- $this->Tree_Options($options); | |
- include_once "Tree/Memory/$type.php"; | |
- $className = 'Tree_Memory_'.$type; | |
- $this->dataSourceClass =& new $className($dsn, $options); | |
+ $this->__construct($config); | |
+ } | |
- // copy the options to be able to get them via getOption(s) | |
- // FIXXME this is not really cool, maybe overwrite | |
- // the *Option* methods!!! | |
- if (isset($this->dataSourceClass->options)) { | |
- $this->options = $this->dataSourceClass->options; | |
+ function __construct($config) | |
+ { | |
+ $type = strtolower($config['type']); | |
+ $this->conf = Tree::arrayMergeClobber($this->conf, $config['options']); | |
+ if ( | |
+ ($type == 'simple' || $type == 'nested') | |
+ && in_array(strtoupper($config['storage']['name']), array('DB', 'MDB', 'MDB2')) | |
+ ) { | |
+ $name = 'SQL'; | |
+ } else { | |
+ $name = strtoupper($config['storage']['name']); | |
} | |
+ include_once 'Tree/Memory/' . $name . $type . '.php'; | |
+ $className = 'Tree_Memory_' . $name . $type; | |
+ | |
+ $this->dataClass = new $className($config); | |
} | |
// }}} | |
+ | |
+ | |
// {{{ switchDataSource() | |
/** | |
@@ -208,15 +203,15 @@ | |
* @param array additional options you can set | |
* @return boolean true on success | |
*/ | |
- function switchDataSource($type, $dsn = '', $options = array()) | |
+ function switchDataSource($config) | |
{ | |
$data = $this->getNode(); | |
//$this->Tree($dsn, $options); | |
- $this->Tree_Memory($type, $GLOBALS['dummy'], $options); | |
+ $this->Tree_Memory($config); | |
// this method prepares data retreived using getNode to be used | |
// in this type of tree | |
- $this->dataSourceClass->setData($data); | |
+ $this->dataClass->setData($data); | |
$this->setup(); | |
} | |
@@ -238,7 +233,7 @@ | |
// for XML an XML-String, | |
// for DB-a result set, may be or an array, dont know here | |
// not implemented yet | |
- $res = $this->dataSourceClass->setupByRawData($string); | |
+ $res = $this->dataClass->setupByRawData($string); | |
return $this->_setup($res); | |
} | |
@@ -255,22 +250,11 @@ | |
*/ | |
function setup($data = null) | |
{ | |
- if ($this->debug) { | |
- $startTime = split(' ',microtime()); | |
- $startTime = $startTime[1]+$startTime[0]; | |
- } | |
- | |
- if (PEAR::isError($res = $this->dataSourceClass->setup($data))) { | |
+ $res = $this->dataClass->setup($data); | |
+ if (PEAR::isError($res)) { | |
return $res; | |
} | |
- if ($this->debug) { | |
- $endTime = split(' ',microtime()); | |
- $endTime = $endTime[1]+$endTime[0]; | |
- echo ' reading and preparing tree data took: '. | |
- ($endTime - $startTime) . '<br>'; | |
- } | |
- | |
return $this->_setup($res); | |
} | |
@@ -288,7 +272,7 @@ | |
*/ | |
function _setup($setupData) | |
{ | |
- // TODO sort by prevId (parentId,prevId $addQuery) too if it exists | |
+ // TODO sort by prevId (parent_id,prevId $addQuery) too if it exists | |
// in the table, or the root might be wrong TODO since the prevId | |
// of the root should be 0 | |
if (!$setupData) { | |
@@ -296,23 +280,52 @@ | |
} | |
//FIXXXXXME validate the structure. | |
- // i.e. a problem occurs, if you give one node, which has a parentId=1, | |
+ // i.e. a problem occurs, if you give one node, which has a parent_id=1, | |
// it screws up everything!!! | |
//empty the data structures, since we are reading the data | |
// from the db (again) | |
- $this->structure = array(); | |
- $this->data = array(); | |
- $this->children = array(); | |
+ $this->structure = $this->data = $this->children = array(); | |
+ | |
// build an array where all the parents have their children as a member | |
// this i do to speed up the buildStructure | |
- $columnNameMappings = $this->getOption('columnNameMaps'); | |
- foreach ($setupData as $values) { | |
+ $copy = $setupData; | |
+ foreach ($setupData as $key => $values) { | |
if (is_array($values)) { | |
$this->data[$values['id']] = $values; | |
- $this->children[$values['parentId']][] = $values['id']; | |
+ $this->children[$values['parent_id']][] = $values['id']; | |
+ $this->structure[$values['id']] = $values['parent_id']; | |
+ | |
+ if ($values['parent_id'] == '0') { | |
+ $this->data[$values['id']]['level'] = 0; | |
+ unset($copy[$key]); | |
+ } | |
+ } else { | |
+ unset($copy[$key]); | |
} | |
} | |
+ unset($setupData); | |
+ // Get the levels for each item. | |
+ do { | |
+ foreach ($copy as $key => $node) { | |
+ if (!array_key_exists('parent_id', $node)) { | |
+ unset($copy[$key]); | |
+ continue; | |
+ } | |
+ | |
+ if (isset($this->data[$node['parent_id']]['level'])) { | |
+ $level = $this->data[$node['parent_id']]['level'] + 1; | |
+ $this->data[$node['id']]['level'] = $level; | |
+ | |
+ if ($level > $this->_treeDepth) { | |
+ $this->_treeDepth = $level; | |
+ } | |
+ unset($copy[$key]); | |
+ } | |
+ } | |
+ } while (count($copy)); | |
+ unset($copy); | |
+ | |
// walk through all the children on each level and set the | |
// next/previous relations of those children, since all children | |
// for "children[$id]" are on the same level we can do | |
@@ -325,93 +338,14 @@ | |
// remember the nextId too, so the build process can | |
// be speed up | |
$this->data[$lastPrevId]['nextId'] = $key; | |
- $this->data[$lastPrevId]['next'] = &$this->data[$key]; | |
$this->data[$key]['prevId'] = $lastPrevId; | |
- $this->data[$key]['previous'] = &$this->data[ $lastPrevId ]; | |
} | |
$lastPrevId = $key; | |
} | |
} | |
} | |
- if ($this->debug) { | |
- $startTime = split(' ',microtime()); | |
- $startTime = $startTime[1] + $startTime[0]; | |
- } | |
- | |
- // when NO prevId is given, sort the entries in each level by the given | |
- // sort order (to be defined) and set the prevId so the build can work | |
- // properly does a prevId exist? | |
- if (!isset($setupData[0]['prevId'])) { | |
- $lastPrevId = 0; | |
- $lastParentId = 0; | |
- $level = 0; | |
- // build the entire recursive relations, so you have 'parentId', | |
- // 'childId', 'nextId', 'prevId' and the references 'child', | |
- // 'parent', 'next', 'previous' set in the property 'data' | |
- foreach($this->data as $key => $value) { | |
- // most if checks in this foreach are for the following reason, | |
- // if not stated otherwise: | |
- // dont make an data[''] or data[0] since this was not read | |
- // from the DB, because id is autoincrement and starts at 1 | |
- // and also in an xml tree there can not be an element </> | |
- // i hope :-) | |
- if ($value['parentId']) { | |
- $this->data[$key]['parent'] = &$this->data[$value['parentId']]; | |
- // the parent has an extra array which contains a reference | |
- // to all it's children, set it here | |
- $this->data[ $value['parentId']]['children'][] = | |
- &$this->data[$key]; | |
- } | |
- | |
- // was a child saved (in the above 'if') | |
- // see comment above | |
- if (isset($this->children[$key]) && | |
- count($this->children[$key]) | |
- ) { | |
- // refer to the first child in the [child] | |
- // and [childId] keys | |
- $this->data[$key]['childId'] = $this->children[$key][0]; | |
- $this->data[$key]['child'] = | |
- &$this->data[$this->children[$key][0]]; | |
- } | |
- | |
- $lastParentId = $value['parentId']; | |
- } | |
- } | |
- | |
- if ($this->debug) { | |
- $endTime = split(' ',microtime()); | |
- $endTime = $endTime[1]+$endTime[0]; | |
- echo ' building took: ' . ($endTime - $startTime) . ' <br>'; | |
- } | |
- | |
- // build the property 'structure' | |
- // empty it, just to be sure everything | |
- //will be set properly | |
- $this->structure = array(); | |
- | |
- if ($this->debug) { | |
- $startTime = split(' ',microtime()); | |
- $startTime = $startTime[1] + $startTime[0]; | |
- } | |
- | |
- // build all the children that are on the root level, if we wouldnt | |
- // do that. We would have to create a root element with an id 0, | |
- // but since this is not read from the db we dont add another element. | |
- // The user wants to get what he had saved | |
- if (isset($this->children[0])) { | |
- foreach ($this->children[0] as $rootElement) { | |
- $this->buildStructure($rootElement, $this->structure); | |
- } | |
- } | |
- | |
- if ($this->debug) { | |
- $endTime = split(' ',microtime()); | |
- $endTime = $endTime[1] + $endTime[0]; | |
- echo ' buildStructure took: ' . ($endTime - $startTime).' <br>'; | |
- } | |
return true; | |
} | |
@@ -434,16 +368,24 @@ | |
* @return mixed either boolean false on failure or the id | |
* of the inserted row | |
*/ | |
- function add($newValues, $parentId = 0, $prevId = 0) | |
+ function add($data, $parent_id = 0, $prevId = 0) | |
{ | |
// see comments in 'move' and 'remove' | |
+ if (method_exists($this->dataClass, 'add')) { | |
+ $result = $this->dataClass->add($data, $parent_id, $prevId); | |
+ /*if (!PEAR::isError($result)) { | |
+ // Setup parent/child relationship | |
+ $this->children[$parent_id][] = $nextId; | |
- if (method_exists($this->dataSourceClass, 'add')) { | |
- return $this->dataSourceClass->add($newValues, $parentId, $prevId); | |
- } else { | |
- return $this->_throwError('method not implemented yet.' , | |
- __LINE__); | |
+ // Add to list of nodes | |
+ $this->structure[$result] = $parent_id; | |
+ | |
+ // Add data | |
+ $this->data[$result] = $newValues; | |
+ }*/ | |
+ return $result; | |
} | |
+ return Tree::raiseError('TREE_ERROR_NOT_IMPLEMENTED'); | |
} | |
// }}} | |
@@ -460,31 +402,39 @@ | |
*/ | |
function remove($id) | |
{ | |
- // if removing recursively is not allowed, which means every child | |
- // should be removed | |
- // then check if this element has a child and return | |
- // "sorry baby cant remove :-) " | |
- if ($this->removeRecursively != true) { | |
- if (isset($this->data[$id]['child'])) { | |
- // TODO raise PEAR warning | |
- return $this->_throwError("Element with id=$id has children ". | |
- "that cant be removed. Set ". | |
- "'setRemoveRecursively' to true to ". | |
- "allow this.", | |
- __LINE__ | |
- ); | |
- } | |
- } | |
- | |
// see comment in 'move' | |
// if the prevId is in use we need to update the prevId of the element | |
// after the one that is removed too, to have the prevId of the one | |
// that is removed!!! | |
- if (method_exists($this->dataSourceClass, 'remove')) { | |
- return $this->dataSourceClass->remove($id); | |
- } else { | |
- return $this->_throwError('method not implemented yet.', __LINE__); | |
+ if (method_exists($this->dataClass, 'remove')) { | |
+ // Remove child nodes first | |
+ if (isset($this->children[$id])) { | |
+ foreach ($this->children[$id] as $child) { | |
+ $this->remove($child); | |
+ } | |
+ } | |
+ | |
+ $result = $this->dataClass->remove($id); | |
+ /*if ($result) { | |
+ // Remove childIDs data | |
+ if (isset($this->children[$id])) { | |
+ unset($this->children[$id]); | |
+ } | |
+ | |
+ // Remove data | |
+ if (isset($this->data[$id])) { | |
+ unset($this->data[$id]); | |
+ } | |
+ | |
+ // Remove from structure array | |
+ if (isset($this->structure[$id])) { | |
+ unset($this->structure[$id]); | |
+ } | |
+ }*/ | |
+ return $result; | |
} | |
+ | |
+ return Tree::raiseError('TREE_ERROR_NOT_IMPLEMENTED'); | |
} | |
// }}} | |
@@ -505,13 +455,46 @@ | |
} | |
// }}} | |
+ // {{{ update() | |
+ | |
+ /** | |
+ * update data in a node | |
+ * | |
+ * @version 2002/01/29 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer the ID of the element that shall be updated | |
+ * @param array the data to update | |
+ * @return mixed either boolean or | |
+ * an error object if the method is not implemented | |
+ */ | |
+ function update($id, $data) | |
+ { | |
+ if (method_exists($this->dataClass, 'update')) { | |
+ $result = $this->dataClass->update($id, $data); | |
+ /*if ($result) { | |
+ // Setup parent/child relationship - Needs to be done a check here to see if it needs unset/add | |
+ $this->children[$data['parent_id'][] = $id; | |
+ | |
+ // Add to list of nodes | |
+ $this->structure[$id] = $data['parent_id']; | |
+ | |
+ // Update data | |
+ $this->data[$id] = $data; | |
+ }*/ | |
+ return $result; | |
+ } | |
+ return Tree::raiseError('TREE_ERROR_NOT_IMPLEMENTED'); | |
+ } | |
+ | |
+ // }}} | |
// {{{ move() | |
/** | |
* move an entry under a given parent or behind a given entry. | |
* !!! the 'move behind another element' is only implemented for nested | |
* trees now!!!. | |
- * If a newPrevId is given the newParentId is dismissed! | |
+ * If a newPrevId is given the newparent_id is dismissed! | |
* call it either like this: | |
* $tree->move(x, y) | |
* to move the element (or entire tree) with the id x | |
@@ -542,12 +525,11 @@ | |
* the beginning | |
* @return boolean true for success | |
*/ | |
- function move($idsToMove, $newParentId, $newPrevId = 0) | |
+ function move($idsToMove, $newparent_id, $newPrevId = 0) | |
{ | |
- settype($idsToMove,'array'); | |
$errors = array(); | |
- foreach ($idsToMove as $idToMove) { | |
- $ret = $this->_move($idToMove, $newParentId, $newPrevId); | |
+ foreach ((array)$idsToMove as $idToMove) { | |
+ $ret = $this->_move($idToMove, $newparent_id, $newPrevId); | |
if (PEAR::isError($ret)) { | |
$errors[] = $ret; | |
} | |
@@ -577,15 +559,14 @@ | |
* if it is 0 it will be put at the beginning | |
* @return mixed true for success, Tree_Error on failure | |
*/ | |
- function _move($idToMove, $newParentId, $prevId = 0) | |
+ function _move($idToMove, $newparent_id, $prevId = 0) | |
{ | |
// itself can not be a parent of itself | |
- if ($idToMove == $newParentId) { | |
- // TODO PEAR-ize error | |
- return TREE_ERROR_INVALID_PARENT; | |
+ if ($idToMove == $newparent_id) { | |
+ return Tree::raiseError('TREE_ERROR_INVALID_PARENT'); | |
} | |
- // check if $newParentId is a child (or a child-child ...) of $idToMove | |
+ // check if $newparent_id is a child (or a child-child ...) of $idToMove | |
// if so prevent moving, because that is not possible | |
// does this element have children? | |
if ($this->hasChildren($idToMove)) { | |
@@ -595,20 +576,18 @@ | |
// (might, not yet) return a reference use while since foreach | |
// only works on a copy of the data to loop through, but we are | |
// changing $allChildren in the loop | |
- while (list(, $aChild) = each ($allChildren)) { | |
+ while (list(, $aChild) = each($allChildren)) { | |
// remove the first element because if array_merge is called | |
// the array pointer seems to be | |
array_shift($allChildren); | |
// set to the beginning and this way the beginning is always | |
// the current element, simply work off and truncate in front | |
if (@$aChild['children']) { | |
- $allChildren = array_merge($allChildren, | |
- $aChild['children'] | |
- ); | |
+ $allChildren = | |
+ array_merge($allChildren, $aChild['children']); | |
} | |
- if ($newParentId == $aChild['id']) { | |
- // TODO PEAR-ize error | |
- return TREE_ERROR_INVALID_PARENT; | |
+ if ($newparent_id == $aChild['id']) { | |
+ return Tree::raiseError('TREE_ERROR_INVALID_PARENT'); | |
} | |
} | |
} | |
@@ -617,103 +596,23 @@ | |
// needs to know where the element should be moved to | |
// and it has to change the prevId of the element that will be after it | |
// so we may be simply call some method like 'update' too? | |
- if (method_exists($this->dataSourceClass, 'move')) { | |
- return $this->dataSourceClass->move($idToMove, | |
- $newParentId, | |
+ if (method_exists($this->dataClass, 'move')) { | |
+ return $this->dataClass->move($idToMove, | |
+ $newparent_id, | |
$prevId | |
); | |
- } else { | |
- return $this->_throwError('method not implemented yet.', __LINE__); | |
} | |
+ return Tree::raiseError('TREE_ERROR_NOT_IMPLEMENTED'); | |
} | |
// }}} | |
- // {{{ update() | |
- /** | |
- * update data in a node | |
- * | |
- * @version 2002/01/29 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the ID of the element that shall be updated | |
- * @param array the data to update | |
- * @return mixed either boolean or | |
- * an error object if the method is not implemented | |
- */ | |
- function update($id, $data) | |
- { | |
- if (method_exists($this->dataSourceClass, 'update')) { | |
- return $this->dataSourceClass->update($id,$data); | |
- } else { | |
- return $this->_throwError( | |
- 'method not implemented yet.', __LINE__ | |
- ); | |
- } | |
- } | |
- | |
- // }}} | |
- | |
// | |
// | |
- // from here all methods are not interacting on the 'dataSourceClass' | |
+ // from here all methods are not interacting on the 'dataClass' | |
// | |
// | |
- // {{{ buildStructure() | |
- /** | |
- * builds the structure in the parameter $insertIn | |
- * this function works recursively down into depth of the folder structure | |
- * it builds an array which goes as deep as the structure goes | |
- * | |
- * @access public | |
- * @version 2001/05/02 | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param integer the parent for which it's structure shall | |
- * be built | |
- * @param integer the array where to build the structure in | |
- * given as a reference to be sure the substructure is built | |
- * in the same array as passed to the function | |
- * @return boolean returns always true | |
- * | |
- */ | |
- function buildStructure($parentId, &$insertIn) | |
- { | |
- // create the element, so it exists in the property "structure" | |
- // also if there are no children below | |
- $insertIn[$parentId] = array(); | |
- | |
- // set the level, since we are walking through the structure here. | |
- // Anyway we can do this here, instead of up in the setup method :-) | |
- // always set the level to one higher than the parent's level, easy ha? | |
- // this applies only to the root element(s) | |
- if (isset($this->data[$parentId]['parent']['level'])) { | |
- $this->data[$parentId]['level'] = | |
- $this->data[$parentId]['parent']['level']+1; | |
- if ($this->data[$parentId]['level']>$this->_treeDepth) { | |
- $this->_treeDepth = $this->data[$parentId]['level']; | |
- } | |
- } else { | |
- // set first level number to 0 | |
- $this->data[$parentId]['level'] = 0; | |
- } | |
- | |
- if (isset($this->children[$parentId]) | |
- && count($this->children[$parentId])) { | |
- // go thru all the folders | |
- foreach ($this->children[$parentId] as $child) { | |
- // build the structure under this folder, | |
- // use the current folder as the new parent and call | |
- // build recursively to build all the children by calling build | |
- // with $insertIn[someindex] the array is filled | |
- // since the array was empty before | |
- $this->buildStructure($child, $insertIn[$parentId]); | |
- } | |
- } | |
- return true; | |
- } | |
- | |
- // }}} | |
// {{{ walk() | |
/** | |
@@ -736,15 +635,20 @@ | |
function walk($walkFunction, $id = 0, $returnType = 'string') | |
{ | |
// by default all of structure is used | |
- $useNode = $this->structure; | |
- if ($id == 0) { | |
+ if ($id === 0) { | |
+ $useNode = $this->structure; | |
$keys = array_keys($this->structure); | |
$id = $keys[0]; | |
} else { | |
// get the path, to be able to go to the element in this->structure | |
$path = $this->getPath($id); | |
+ if (empty($path)) { | |
+ return array(); | |
+ } | |
+ | |
// pop off the last element, since it is the one requested | |
array_pop($path); | |
+ | |
// start at the root of structure | |
$curNode = $this->structure; | |
foreach ($path as $node) { | |
@@ -787,27 +691,29 @@ | |
*/ | |
function _walk($walkFunction, &$curLevel, $returnType) | |
{ | |
- if (count($curLevel)) { | |
+ if (isset($curLevel) && is_array($curLevel)) { | |
foreach ($curLevel as $key => $value) { | |
$ret = call_user_func($walkFunction, $this->data[$key]); | |
+ | |
switch ($returnType) { | |
- case 'array': | |
- $this->walkReturn[] = $ret; | |
- break; | |
- // this only adds the element if the $ret is an array | |
- // and contains data | |
- case 'ifArray': | |
- if (is_array($ret)) { | |
+ case 'array': | |
$this->walkReturn[] = $ret; | |
- } | |
- break; | |
- default: | |
- $this->walkReturn.= $ret; | |
- break; | |
+ break; | |
+ // this only adds the element if the $ret is an array | |
+ // and contains data | |
+ case 'ifArray': | |
+ if (is_array($ret)) { | |
+ $this->walkReturn[] = $ret; | |
+ } | |
+ break; | |
+ default: | |
+ $this->walkReturn .= $ret; | |
+ break; | |
} | |
$this->_walk($walkFunction, $value, $returnType); | |
} | |
} | |
+ | |
return $this->walkReturn; | |
} | |
@@ -821,7 +727,7 @@ | |
* one element). | |
* The following array $x passed as the parameter | |
* $x[0] = array('name' => 'bla', | |
- * 'parentId' => '30', | |
+ * 'parent_id' => '30', | |
* array('name' => 'bla1', | |
* 'comment' => 'foo', | |
* array('name' => 'bla2'), | |
@@ -830,10 +736,10 @@ | |
* array('name'=>'bla1_1'), | |
* ); | |
* $x[1] = array('name' => 'fooBla', | |
- * 'parentId' => '30'); | |
+ * 'parent_id' => '30'); | |
* | |
* would add the following tree (or subtree/node) under the parent | |
- * with the id 30 (since 'parentId'=30 in $x[0] and in $x[1]): | |
+ * with the id 30 (since 'parent_id'=30 in $x[0] and in $x[1]): | |
* +--bla | |
* | +--bla1 | |
* | | +--bla2 | |
@@ -867,16 +773,16 @@ | |
} | |
} | |
// add the element and get the id, that it got, to have | |
- // the parentId for the children | |
+ // the parent_id for the children | |
$insertedId = $this->add($newEntry); | |
// if inserting suceeded, we have received the id | |
// under which we can insert the children | |
- if ($insertedId!= false) { | |
- // if there are children, set their parentId. | |
+ if ($insertedId != false) { | |
+ // if there are children, set their parent_id. | |
// So they kknow where they belong in the tree | |
if (count($newNode)) { | |
foreach($newNode as $key => $aNewNode) { | |
- $newNode[$key]['parentId'] = $insertedId; | |
+ $newNode[$key]['parent_id'] = $insertedId; | |
} | |
} | |
// call yourself recursively to insert the children | |
@@ -906,17 +812,18 @@ | |
*/ | |
function getPath($id) | |
{ | |
+ if (!(int)$id) { | |
+ return array(); | |
+ } | |
+ | |
// empty the path, to be clean | |
$path = array(); | |
- // FIXXME may its better to use a for(level) to count down, | |
- // since a while is always a little risky | |
- // until there are no more parents | |
- while (@$this->data[$id]['parent']) { | |
+ while (@$this->data[$id]['parent_id']) { | |
// curElement is already a reference, so save it in path | |
$path[] = &$this->data[$id]; | |
// get the next parent id, for the while to retreive the parent's parent | |
- $id = $this->data[$id]['parent']['id']; | |
+ $id = $this->data[$id]['parent_id']; | |
} | |
// dont forget the last one | |
$path[] = &$this->data[$id]; | |
@@ -925,24 +832,6 @@ | |
} | |
// }}} | |
- // {{{ setRemoveRecursively() | |
- | |
- /** | |
- * sets the remove-recursively mode, either true or false | |
- * | |
- * @version 2001/10/09 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param boolean set to true if removing a tree level | |
- * shall remove all it's children and theit children | |
- * | |
- */ | |
- function setRemoveRecursively($case=true) | |
- { | |
- $this->removeRecursively = $case; | |
- } | |
- | |
- // }}} | |
// {{{ _getElement() | |
/** | |
@@ -960,36 +849,15 @@ | |
// element that is requested. | |
$element = null; | |
- if ($what == '') { | |
- $element = $this->data[$id]; | |
+ if ($what == '' && isset($this->data[$id])) { | |
+ $element = &$this->_prepareResult($this->data[$id]); | |
} | |
- $elementId = $this->_getElementId($id, $what); | |
- if ($elementId !== null) { | |
- $element = $this->data[$elementId]; | |
+ | |
+ if (isset($this->data[$id][$what])) { | |
+ $element = &$this->_prepareResult($this->data[$this->data[$id][$what]]); | |
} | |
- // we should not return false, since that might be a value | |
- // of the element that is requested | |
- return $element; | |
- } | |
- // }}} | |
- // {{{ _getElementId() | |
- | |
- /** | |
- * | |
- * | |
- * @version 2002/01/21 | |
- * @access private | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param int the element ID | |
- * | |
- */ | |
- function _getElementId($id, $what) | |
- { | |
- if (isset($this->data[$id][$what]) && $this->data[$id][$what]) { | |
- return $this->data[$id][$what]['id']; | |
- } | |
- return null; | |
+ return $element;; | |
} | |
// }}} | |
@@ -1021,6 +889,7 @@ | |
* @author Wolfram Kriesing <[email protected]> | |
* @param mixed either the id of an element | |
* or the path to the element | |
+ * @param string the field name | |
* | |
*/ | |
function getElementContent($idOrPath, $fieldName) | |
@@ -1041,6 +910,7 @@ | |
* @access private | |
* @author Wolfram Kriesing <[email protected]> | |
* @param int the element ID | |
+ * @param string the field name | |
* | |
*/ | |
function getElementsContent($ids, $fieldName) { | |
@@ -1048,7 +918,7 @@ | |
// Since it only serves my lazyness | |
// is this effective here? i can also loop in the calling code!? | |
$fields = array(); | |
- if (is_array($ids) && count($ids)) { | |
+ if (isset($ids) && is_array($ids) && count($ids)) { | |
foreach ($ids as $aId) { | |
$fields[] = $this->getElementContent($aId, $fieldName); | |
} | |
@@ -1074,12 +944,14 @@ | |
*/ | |
function &getElementByPath($path, $startId = 0, $nodeName = 'name', $seperator = '/') | |
{ | |
+ // null since false might be interpreted as id 0 | |
$element = null; | |
- $id = $this->getIdByPath($path,$startId); | |
+ | |
+ $id = $this->getIdByPath($path, $startId); | |
if ($id) { | |
- $element = &$this->getElement($id); | |
+ $element = &$this->_getElement($id); | |
} | |
- // return null since false might be interpreted as id 0 | |
+ | |
return $element; | |
} | |
@@ -1101,26 +973,6 @@ | |
} | |
// }}} | |
- // {{{ getChild() | |
- | |
- /** | |
- * returns the child if the node given has one | |
- * !!! ATTENTION watch out that you never change any of the data returned, | |
- * since they are references to the internal property $data | |
- * | |
- * @version 2001/11/27 | |
- * @access public | |
- * @author Wolfram Kriesing <[email protected]> | |
- * @param mixed the id of the node to get the child for | |
- * | |
- */ | |
- function &getChild($id) | |
- { | |
- $element = &$this->_getElement($id, 'child'); | |
- return $element; | |
- } | |
- | |
- // }}} | |
// {{{ getParent() | |
/** | |
@@ -1136,12 +988,12 @@ | |
*/ | |
function &getParent($id) | |
{ | |
- $element = &$this->_getElement($id, 'parent'); | |
+ $element = &$this->_getElement($id, 'parent_id'); | |
return $element; | |
} | |
// }}} | |
- // {{{ getNext() | |
+ // {{{ nextSibling() | |
/** | |
* returns the next element if the node given has one | |
@@ -1154,14 +1006,14 @@ | |
* @param mixed the id of the node to get the child for | |
* @return mixed reference to the next element or false if there is none | |
*/ | |
- function &getNext($id) | |
+ function &nextSibling($id) | |
{ | |
- $element = &$this->_getElement($id, 'next'); | |
+ $element = &$this->_getElement($id, 'nextId'); | |
return $element; | |
} | |
// }}} | |
- // {{{ getPrevious() | |
+ // {{{ prevSibling() | |
/** | |
* returns the previous element if the node given has one | |
@@ -1174,9 +1026,9 @@ | |
* @param mixed the id of the node to get the child for | |
* @return mixed reference to the next element or false if there is none | |
*/ | |
- function &getPrevious($id) | |
+ function &prevSibling($id) | |
{ | |
- $element = &$this->_getElement($id, 'previous'); | |
+ $element = &$this->_getElement($id, 'prevId'); | |
return $element; | |
} | |
@@ -1197,8 +1049,8 @@ | |
/* | |
function &getNode($id) | |
{ | |
- //$element = &$this->_getElement($id); | |
- //return $element; | |
+ $element = &$this->_getElement($id); | |
+ return $element; | |
} | |
*/ | |
@@ -1227,38 +1079,48 @@ | |
{ | |
// if no start ID is given get the root | |
if ($startId == 0) { | |
- $startId = $this->getFirstRootId(); | |
+ $root = $this->getFirstRoot(); | |
+ $startId = $root['id']; | |
} else { // if a start id is given, get its first child to start searching there | |
- $startId = $this->getChildId($startId); | |
- if ($startId==false) { // is there a child to this element? | |
+ $startId = $this->children[$startId][0]; | |
+ if ($startId === false) { // is there a child to this element? | |
return false; | |
} | |
} | |
- if (strpos($path,$seperator) === 0) { // if a seperator is at the beginning strip it off | |
- $path = substr($path,strlen($seperator)); | |
+ // if a seperator is at the beginning strip it off | |
+ if (strpos($path, $seperator) === 0) { | |
+ $path = substr($path, strlen($seperator)); | |
} | |
+ | |
$nodes = explode($seperator, $path); | |
+ $nodeCount = count($nodes); | |
$curId = $startId; | |
+ | |
foreach ($nodes as $key => $aNodeName) { | |
$nodeFound = false; | |
do { | |
- if ($this->data[$curId][$nodeName] == $aNodeName) { | |
+ if (isset($this->data[$curId][$nodeName]) && | |
+ $this->data[$curId][$nodeName] == $aNodeName | |
+ ) { | |
$nodeFound = true; | |
// do only save the child if we are not already at the end of path | |
// because then we need curId to return it | |
- if ($key < (count($nodes) - 1)) { | |
- $curId = $this->getChildId($curId); | |
+ if ($key < ($nodeCount - 1)) { | |
+ $curId = $this->children[$curId][0]; | |
} | |
break; | |
} | |
- $curId = $this->getNextId($curId); | |
+ | |
+ $next = $this->nextSibling($curId); | |
+ $curId = $next['id']; | |
} while($curId); | |
- if ($nodeFound == false) { | |
+ if ($nodeFound === false) { | |
return false; | |
} | |
} | |
+ | |
return $curId; | |
// FIXXME to be implemented | |
} | |
@@ -1291,7 +1153,7 @@ | |
/** | |
* since in a nested tree there can only be one root | |
* which i think (now) is correct, we also need an alias for this method | |
- * this also makes all the methods in Tree_Common, which access the | |
+ * this also makes all the methods in Tree, which access the | |
* root element work properly! | |
* | |
* @access public | |
@@ -1301,19 +1163,19 @@ | |
*/ | |
function &getRoot() | |
{ | |
- $tmp = $this->getFirstRoot(); | |
- return $tmp; | |
+ $element = &$this->getFirstRoot(); | |
+ return $element; | |
} | |
// }}} | |
- // {{{ getRoot() | |
+ // {{{ getBranch() | |
/** | |
* gets the tree under the given element in one array, sorted | |
* so you can go through the elements from begin to end and list them | |
* as they are in the tree, where every child (until the deepest) is retreived | |
* | |
- * @see &_getNode() | |
+ * @see &_getBranch() | |
* @access public | |
* @version 2001/12/17 | |
* @author Wolfram Kriesing <[email protected]> | |
@@ -1323,24 +1185,20 @@ | |
* retreived | |
* @return array sorted as listed in the tree | |
*/ | |
- function &getNode($startId=0, $depth=0) | |
+ function &getBranch($startId = 0, $depth = 0) | |
{ | |
- if ($startId == 0) { | |
- $level = 0; | |
- } else { | |
- $level = $this->getLevel($startId); | |
- } | |
+ $level = $startId == 0 ? 0 : $this->getLevel($startId); | |
$this->_getNodeMaxLevel = $depth ? ($depth + $level) : 0 ; | |
//!!! $this->_getNodeCurParent = $this->data['parent']['id']; | |
// if the tree is empty dont walk through it | |
if (!count($this->data)) { | |
- $tmp = null; | |
- return $tmp; | |
+ $a = array(); | |
+ return $a; | |
} | |
- $ret = $this->walk(array(&$this,'_getNode'), $startId, 'ifArray'); | |
+ $ret = $this->walk(array(&$this, '_getBranch'), $startId, 'ifArray'); | |
return $ret; | |
} | |
@@ -1351,7 +1209,7 @@ | |
* this is used for walking through the tree structure | |
* until a given level, this method should only be used by getNode | |
* | |
- * @see &getNode() | |
+ * @see &getBranch() | |
* @see walk() | |
* @see _walk() | |
* @access private | |
@@ -1361,15 +1219,15 @@ | |
* @return mixed either returns the node, or nothing | |
* if the level _getNodeMaxLevel is reached | |
*/ | |
- function &_getNode(&$node) | |
+ function &_getBranch(&$node) | |
{ | |
if ($this->_getNodeMaxLevel) { | |
if ($this->getLevel($node['id']) < $this->_getNodeMaxLevel) { | |
return $node; | |
} | |
- $tmp = null; | |
- return $tmp; | |
+ return; | |
} | |
+ | |
return $node; | |
} | |
@@ -1382,23 +1240,32 @@ | |
* @version 2001/12/17 | |
* @access public | |
* @author Wolfram Kriesing <[email protected]> | |
- * @param integer $id the id of the node to check for children | |
+ * @param integer|array $id the id of the node to check for children | |
+ * @param boolean if only the first child should be returned (only used when one id is passed) | |
* @param integer the children of how many levels shall be returned | |
+ | |
* @return boolean true if the node has children | |
*/ | |
- function getChildren($ids, $levels = 1) | |
+ function getChildren($ids, $oneChild = false, $levels = 1) | |
{ | |
//FIXXME $levels to be implemented | |
$ret = array(); | |
if (is_array($ids)) { | |
foreach ($ids as $aId) { | |
if ($this->hasChildren($aId)) { | |
- $ret[$aId] = $this->data[$aId]['children']; | |
+ foreach ($this->children[$aId] as $value) { | |
+ $ret[$aId][] = $this->data[$value]; | |
+ } | |
} | |
} | |
} else { | |
if ($this->hasChildren($ids)) { | |
- $ret = $this->data[$ids]['children']; | |
+ foreach ($this->children[$ids] as $value) { | |
+ $ret[] = $this->data[$value]; | |
+ if ($oneChild) { | |
+ return $ret = $ret[0]; | |
+ } | |
+ } | |
} | |
} | |
return $ret; | |
@@ -1422,6 +1289,24 @@ | |
} | |
// }}} | |
+ | |
+ /** | |
+ * returns if the given element has any children | |
+ * | |
+ * @version 2001/12/17 | |
+ * @access public | |
+ * @author Wolfram Kriesing <[email protected]> | |
+ * @param integer $id the id of the node to check for children | |
+ * @return boolean true if the node has children | |
+ */ | |
+ function hasChildren($id = 0) | |
+ { | |
+ if (isset($this->children[$id])) { | |
+ return true; | |
+ } | |
+ return false; | |
+ } | |
+ | |
// {{{ varDump() | |
/** | |
@@ -1445,7 +1330,7 @@ | |
// if $node is an array, we assume it is a collection of elements | |
if (!is_array($node)) { | |
- $nodes = $this->getNode($node); | |
+ $nodes = $this->getBranch($node); | |
} else { | |
$nodes = $node; | |
} | |
@@ -1496,23 +1381,21 @@ | |
*/ | |
function copy($srcId, $destId) | |
{ | |
- if (method_exists($this->dataSourceClass, 'copy')) { | |
- return $this->dataSourceClass->copy($srcId, $destId); | |
- } else { | |
- return $this->_throwError('method not implemented yet.', __LINE__); | |
+ if (method_exists($this->dataClass, 'copy')) { | |
+ return $this->dataClass->copy($srcId, $destId); | |
} | |
+ return Tree::raiseError('TREE_ERROR_NOT_IMPLEMENTED'); | |
/* | |
remove all array elements after 'parent' since those had been created | |
- and remove id and set parentId and that should be it, build the tree and pass it to addNode | |
+ and remove id and set parent_id and that should be it, build the tree and pass it to addNode | |
those are the fields in one data-entry | |
id=>41 | |
-parentId=>39 | |
+parent_id=>39 | |
name=>Java | |
parent=>Array | |
prevId=>58 | |
previous=>Array | |
-childId=>77 | |
child=>Array | |
nextId=>104 | |
next=>Array | |
@@ -1526,4 +1409,6 @@ | |
} | |
// }}} | |
+ | |
} | |
+?> | |
\ No newline at end of file | |
Property changes on: Tree/Memory.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.34.2.3 | |
+1.35 | |
Index: tests/getElementTest.php | |
=================================================================== | |
--- tests/getElementTest.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ tests/getElementTest.php (.../trunk) (revision 321102) | |
@@ -1,37 +1,17 @@ | |
<?php | |
-// | |
// $Id$ | |
-// | |
require_once dirname(__FILE__) . '/TreeHelper.php'; | |
class tests_getElementTest extends TreeHelper | |
{ | |
- /** | |
- * There was a bug when we mapped column names, especially when we mapped | |
- * a column to the same name as the column. We check this here too. | |
- * | |
- * | |
- */ | |
function test_MemoryDBnested() | |
{ | |
$tree = $this->getMemoryDBnested(); | |
$tree->update(3, array('comment' => 'PEAR rulez')); | |
$tree->setup(); | |
$actual = $tree->getElement(3); | |
- $this->assertEquals('PEAR rulez', $actual['comment'], 'Original:'); | |
- | |
- $tree->setOption('columnNameMaps', array('comment' => 'comment')); | |
- $actual = $tree->getElement(3); | |
- $this->assertEquals('PEAR rulez', $actual['comment'], 'Map to same name:'); | |
- | |
- // This doesn't work. I took a quick look to try and fix it. What | |
- // a mess. Considering how much I've already fixed, I just don't | |
- // care anymore. Marking it incomplete. --Dan | |
- $this->markTestIncomplete(); | |
- $tree->setOption('columnNameMaps', array('myComment' => 'comment')); | |
- $actual = $tree->getElement(3); | |
- $this->assertEquals('PEAR rulez', $actual['myComment'], 'Map to different name:'); | |
+ $this->assertEquals('PEAR rulez', $actual['comment']); | |
} | |
function test_MemoryMDBnested() | |
@@ -46,13 +26,10 @@ | |
$actual = $tree->getElement(3); | |
$this->assertEquals('PEAR rulez', $actual['comment']); | |
- $tree->setOption('columnNameMaps', array('comment' => 'comment')); | |
+ $tree->setOption('fields', array('comment' => array('type' => 'text', 'name' => 'myComment'))); | |
+ $tree->setup(); | |
$actual = $tree->getElement(3); | |
$this->assertEquals('PEAR rulez', $actual['comment']); | |
- | |
- $tree->setOption('columnNameMaps', array('myComment' => 'comment')); | |
- $actual = $tree->getElement(3); | |
- $this->assertEquals('PEAR rulez', $actual['myComment']); | |
} | |
// do this for XML | |
@@ -61,21 +38,11 @@ | |
// do this for DBsimple | |
- // do this for DynamicDBnested | |
+ // do this for Dynamic[M]DB[2]nested | |
function test_DynamicDBnested() | |
{ | |
- $tree =& $this->getDynamicDBnested(); | |
- $tree->update(3, array('comment' => 'PEAR rulez')); | |
- $actual = $tree->getElement(3); | |
- $this->assertEquals('PEAR rulez', $actual['comment']); | |
- | |
- $tree->setOption('columnNameMaps', array('comment' => 'comment')); | |
- $actual = $tree->getElement(3); | |
- $this->assertEquals('PEAR rulez', $actual['comment']); | |
- | |
- $tree->setOption('columnNameMaps', array('myComment' => 'comment')); | |
- $actual = $tree->getElement(3); | |
- $this->assertEquals('PEAR rulez', $actual['myComment']); | |
+ $tree =& $this->getDynamicSQLnested('DB'); | |
+ $this->_test_DynamicSQLnested($tree); | |
} | |
function test_DynamicMDBnested() | |
@@ -84,18 +51,25 @@ | |
$this->markTestSkipped('MDB is not installed'); | |
} | |
- $tree =& $this->getDynamicMDBnested(); | |
+ $tree =& $this->getDynamicSQLnested('MDB'); | |
+ $this->_test_DynamicSQLnested($tree); | |
+ } | |
+ | |
+ function test_DynamicMDB2nested() | |
+ { | |
+ if (!$this->has_mdb2) { | |
+ $this->markTestSkipped('MDB2 is not installed'); | |
+ } | |
+ | |
+ $tree =& $this->getDynamicSQLnested('MDB2'); | |
+ $this->_test_DynamicSQLnested($tree); | |
+ } | |
+ | |
+ function _test_DynamicSQLnested(&$tree) | |
+ { | |
$tree->update(3, array('comment' => 'PEAR rulez')); | |
$actual = $tree->getElement(3); | |
$this->assertEquals('PEAR rulez', $actual['comment']); | |
- | |
- $tree->setOption('columnNameMaps', array('comment' => 'comment')); | |
- $actual = $tree->getElement(3); | |
- $this->assertEquals('PEAR rulez', $actual['comment']); | |
- | |
- $tree->setOption('columnNameMaps', array('myComment' => 'comment')); | |
- $actual = $tree->getElement(3); | |
- $this->assertEquals('PEAR rulez', $actual['myComment']); | |
} | |
/** | |
@@ -103,48 +77,43 @@ | |
* | |
* | |
*/ | |
- function test_DynamicDBnestedEmptyTree() | |
+ function test_DynamicSQLnestedEmptyTree() | |
{ | |
- $tree = Tree::setup('Dynamic_DBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
- $tree->remove($tree->getRootId()); | |
- | |
- $tree = Tree::setup('Memory_DBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
- $tree->setup(); | |
- $id = $tree->add(array('name' => 'Start')); | |
- $tree->setup(); | |
- $el = $tree->getElement($id); | |
- $this->assertEquals('Start', $el['name']); | |
- $tree->remove($tree->getRootId()); | |
- | |
- $tree = Tree::setup('Dynamic_DBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
- $id = $tree->add(array('name' => 'StartDyn')); | |
- $el = $tree->getElement($id); | |
- $this->assertEquals('StartDyn', $el['name']); | |
- } | |
+ $config = array( | |
+ 'container' => 'Dynamic', | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => 'DB', | |
+ 'dsn' => $this->dsn, | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => TABLE_TREENESTED, | |
+ 'order' => 'id', | |
+ 'fields' => array(), | |
+ ), | |
+ ); | |
- function test_DynamicMDBnestedEmptyTree() | |
- { | |
- if (!$this->has_mdb) { | |
- $this->markTestSkipped('MDB is not installed'); | |
- } | |
+ $tree = Tree::factory($config); | |
+ $root = $tree->getRoot(); | |
+ $tree->remove($root['id']); | |
- $tree = Tree::setup('Dynamic_MDBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
- $tree->remove($tree->getRootId()); | |
- | |
- $tree = Tree::setup('Memory_MDBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
+ $config['container'] = 'Memory'; | |
+ $tree = Tree::factory($config); | |
$tree->setup(); | |
$id = $tree->add(array('name' => 'Start')); | |
$tree->setup(); | |
$el = $tree->getElement($id); | |
$this->assertEquals('Start', $el['name']); | |
- $tree->remove($tree->getRootId()); | |
- | |
- $tree = Tree::setup('Dynamic_MDBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
+ $root = $tree->getRoot(); | |
+ $tree->remove($root['id']); | |
+ | |
+ $config['container'] = 'Dynamic'; | |
+ $tree = Tree::factory($config); | |
$id = $tree->add(array('name' => 'StartDyn')); | |
$el = $tree->getElement($id); | |
$this->assertEquals('StartDyn', $el['name']); | |
- } | |
- | |
+ } | |
} | |
?> | |
Property changes on: tests/getElementTest.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3 | |
+1.4 | |
Index: tests/getPathTest.php | |
=================================================================== | |
--- tests/getPathTest.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ tests/getPathTest.php (.../trunk) (revision 321102) | |
@@ -1,7 +1,5 @@ | |
<?php | |
-// | |
// $Id$ | |
-// | |
require_once dirname(__FILE__) . '/TreeHelper.php'; | |
@@ -30,29 +28,19 @@ | |
// do this for DBsimple | |
- // do this for DynamicDBnested | |
- function test_DynamicDBnested() | |
+ // do this for DynamicSQLnested | |
+ function test_DynamicSQLnested() | |
{ | |
- $tree =& $this->getDynamicDBnested(); | |
+ $tree =& $this->getDynamicSQLnested(); | |
$this->_testPath($tree); | |
} | |
- | |
- function test_DynamicMDBnested() | |
- { | |
- if (!$this->has_mdb) { | |
- $this->markTestSkipped('MDB is not installed'); | |
- } | |
- | |
- $tree =& $this->getDynamicMDBnested(); | |
- $this->_testPath($tree); | |
- } | |
function _testPath(&$tree) | |
{ | |
// $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
$id = 5; | |
$path = $tree->getPath($id); | |
- | |
+ | |
$this->assertEquals(3, sizeof($path)); | |
$this->assertEquals('Root', $path[0]['name']); | |
$this->assertEquals('child 2', $path[1]['name']); | |
Property changes on: tests/getPathTest.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.2 | |
+1.3 | |
Index: tests/removeTest.php | |
=================================================================== | |
--- tests/removeTest.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ tests/removeTest.php (.../trunk) (revision 321102) | |
@@ -1,7 +1,5 @@ | |
<?php | |
-// | |
// $Id$ | |
-// | |
require_once dirname(__FILE__) . '/TreeHelper.php'; | |
@@ -31,7 +29,7 @@ | |
{ | |
$tree = $this->getMemoryDBnested(); | |
// $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- $parentId = $tree->getParentId(5); | |
+ $parent = $tree->getParent(5); | |
$ret = $tree->move(5, 5); | |
$tree->setup(); | |
@@ -42,7 +40,8 @@ | |
$this->fail('Expected TRUE but got a ' . gettype($ret)); | |
} | |
- $this->assertEquals($parentId, $tree->getParentId(5)); | |
+ $parent1 = $tree->getParent(5); | |
+ $this->assertEquals($parent['id'], $parent1['id']); | |
} | |
function test_MemoryMDBnestedNoAction() | |
@@ -53,7 +52,7 @@ | |
$tree = $this->getMemoryMDBnested(); | |
// $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- $parentId = $tree->getParentId(5); | |
+ $parent = $tree->getParent(5); | |
$ret = $tree->move(5, 5); | |
$tree->setup(); | |
@@ -64,7 +63,8 @@ | |
$this->fail('Expected TRUE but got a ' . gettype($ret)); | |
} | |
- $this->assertEquals($parentId, $tree->getParentId(5)); | |
+ $parent1 = $tree->getParent(5); | |
+ $this->assertEquals($parent['id'], $parent1['id']); | |
} | |
// do this for XML | |
@@ -73,10 +73,10 @@ | |
// do this for DBsimple | |
- // do this for DynamicDBnested | |
- function test_DynamicDBnested() | |
+ // do this for DynamicSQLnested | |
+ function test_DynamicSQLnested() | |
{ | |
- $tree =& $this->getDynamicDBnested(); | |
+ $tree =& $this->getDynamicSQLnested(); | |
$ret = $tree->remove(5); | |
// Avoid PHPUnit exhausting memory if $ret is a large array or object. | |
@@ -96,33 +96,6 @@ | |
$this->fail('Expected TRUE but got a ' . gettype($ret)); | |
} | |
} | |
- | |
- function test_DynamicMDBnested() | |
- { | |
- if (!$this->has_mdb) { | |
- $this->markTestSkipped('MDB is not installed'); | |
- } | |
- | |
- $tree =& $this->getDynamicMDBnested(); | |
- $ret = $tree->remove(5); | |
- | |
- // Avoid PHPUnit exhausting memory if $ret is a large array or object. | |
- if (is_bool($ret)) { | |
- $this->assertTrue($ret); | |
- } else { | |
- $this->fail('Expected TRUE but got a ' . gettype($ret)); | |
- } | |
- | |
- // and check if the element doesnt exist anymore ... this is not 100% sure, sicne the | |
- // returned error message is a string :-( | |
- // Avoid PHPUnit exhausting memory if $ret is a large array or object. | |
- $ret = Tree::isError($tree->getElement(5)); | |
- if (is_bool($ret)) { | |
- $this->assertTrue($ret); | |
- } else { | |
- $this->fail('Expected TRUE but got a ' . gettype($ret)); | |
- } | |
- } | |
} | |
?> | |
Property changes on: tests/removeTest.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3.2.1 | |
+1.4 | |
Index: tests/TreeHelper.php | |
=================================================================== | |
--- tests/TreeHelper.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ tests/TreeHelper.php (.../trunk) (revision 321102) | |
@@ -1,7 +1,5 @@ | |
<?php | |
-// | |
// $Id$ | |
-// | |
if (!defined('TABLE_TREENESTED')) { | |
if ($fp = @fopen('PHPUnit/Autoload.php', 'r', true)) { | |
@@ -59,8 +57,8 @@ | |
function setUp() | |
{ | |
- // common setup, setup the table structure and data in the db | |
- // (this actually also does the tearDown, since we have the DROP TABLE queries in the setup too | |
+ // common factory, factory the table structure and data in the db | |
+ // (this actually also does the tearDown, since we have the DROP TABLE queries in the factory too | |
require 'sql.php'; | |
$this->dsn = unserialize(DB_DSN); | |
$db = DB::connect($this->dsn); | |
@@ -107,30 +105,72 @@ | |
function &getMemoryDBnested() | |
{ | |
- $tree = Tree::setup('Memory_DBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
+ $config = array( | |
+ 'container' => 'Memory', | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => 'DB', | |
+ 'dsn' => $this->dsn, | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => TABLE_TREENESTED, | |
+ 'order' => 'id', | |
+ 'fields' => array( | |
+ 'comment' => array('type' => 'text', 'name' => 'comment'), | |
+ ), | |
+ ), | |
+ ); | |
+ $tree = Tree::factory($config); | |
$tree->setup(); | |
return $tree; | |
} | |
- function &getDynamicDBnested() | |
+ function &getDynamicSQLnested($name = 'DB') | |
{ | |
- $tree = Tree::setup('Dynamic_DBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
+ $config = array( | |
+ 'container' => 'Dynamic', | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => $name, | |
+ 'dsn' => $this->dsn, | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => TABLE_TREENESTED, | |
+ 'order' => 'id', | |
+ 'fields' => array( | |
+ 'comment' => array('type' => 'text', 'name' => 'comment'), | |
+ ), | |
+ ), | |
+ ); | |
+ $tree = Tree::factory($config); | |
+ | |
return $tree; | |
} | |
function &getMemoryMDBnested() | |
{ | |
- $tree = Tree::setup('Memory_MDBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
+ $config = array( | |
+ 'container' => 'Memory', | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => 'MDB', | |
+ 'dsn' => $this->dsn, | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => TABLE_TREENESTED, | |
+ 'order' => 'id', | |
+ 'fields' => array( | |
+ 'comment' => array('type' => 'text', 'name' => 'comment'), | |
+ ), | |
+ ), | |
+ ); | |
+ $tree = Tree::factory($config); | |
$tree->setup(); | |
return $tree; | |
} | |
- | |
- function &getDynamicMDBnested() | |
- { | |
- $tree = Tree::setup('Dynamic_MDBnested', $this->dsn, array('table' => TABLE_TREENESTED)); | |
- return $tree; | |
- } | |
- | |
} | |
?> | |
Property changes on: tests/TreeHelper.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3 | |
+1.4 | |
Index: tests/sql.php | |
=================================================================== | |
--- tests/sql.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ tests/sql.php (.../trunk) (revision 321102) | |
Property changes on: tests/sql.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.1 | |
+1.2 | |
Index: tests/getIdByPathTest.php | |
=================================================================== | |
--- tests/getIdByPathTest.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ tests/getIdByPathTest.php (.../trunk) (revision 321102) | |
@@ -1,7 +1,5 @@ | |
<?php | |
-// | |
// $Id$ | |
-// | |
require_once dirname(__FILE__) . '/TreeHelper.php'; | |
@@ -10,9 +8,9 @@ | |
// check if we get the right ID, for the given path | |
function test_MemoryDBnested() | |
{ | |
- $tree = $this->getMemoryDBnested(); | |
- $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- | |
+ $tree = $this->getMemoryDBnested(); | |
+ $id = $tree->getIdByPath('Root/child 2/child 2_2'); | |
+ | |
$this->assertEquals(5, $id); | |
} | |
@@ -22,8 +20,8 @@ | |
$this->markTestSkipped('MDB is not installed'); | |
} | |
- $tree = $this->getMemoryMDBnested(); | |
- $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
+ $tree = $this->getMemoryMDBnested(); | |
+ $id = $tree->getIdByPath('Root/child 2/child 2_2'); | |
$this->assertEquals(5, $id); | |
} | |
@@ -34,27 +32,16 @@ | |
// do this for DBsimple | |
- // do this for DynamicDBnested | |
- function test_DynamicDBnested() | |
+ // do this for DynamicSQLnested | |
+ function test_DynamicSQLnested() | |
{ | |
- $tree = $this->getDynamicDBnested(); | |
+ $tree = $this->getDynamicSQLnested(); | |
$id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- $this->assertEquals(5, $id,'This is not implemented, yet!!! (This test should fail ... for now)'); | |
- } | |
- | |
- function test_DynamicMDBnested() | |
- { | |
- if (!$this->has_mdb) { | |
- $this->markTestSkipped('MDB is not installed'); | |
- } | |
+ $this->markTestIncomplete(); | |
- $tree = $this->getDynamicMDBnested(); | |
- $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- | |
- $this->assertEquals(5, $id,'This is not implemented, yet!!! (This test should fail ... for now)'); | |
+ $this->assertEquals(5, $id, 'This is not implemented, yet!!! (This test should fail ... for now)'); | |
} | |
- | |
} | |
?> | |
Property changes on: tests/getIdByPathTest.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3 | |
+1.4 | |
Index: tests/moveTest.php | |
=================================================================== | |
--- tests/moveTest.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ tests/moveTest.php (.../trunk) (revision 321102) | |
@@ -1,7 +1,5 @@ | |
<?php | |
-// | |
// $Id$ | |
-// | |
require_once dirname(__FILE__) . '/TreeHelper.php'; | |
@@ -22,7 +20,8 @@ | |
} | |
// and check if the move succeeded, by checking the new parentId | |
- $this->assertEquals(1,$tree->getParentId(5)); | |
+ $parent = $tree->getParent(5); | |
+ $this->assertEquals(1, $parent['id']); | |
} | |
function test_MemoryMDBnested() | |
@@ -43,14 +42,15 @@ | |
} | |
// and check if the move succeeded, by checking the new parentId | |
- $this->assertEquals(1, $tree->getParentId(5)); | |
+ $parent = $tree->getParent(5); | |
+ $this->assertEquals(1, $parent['id']); | |
} | |
function test_MemoryDBnestedNoAction() | |
{ | |
$tree = $this->getMemoryDBnested(); | |
// $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- $parentId = $tree->getParentId(5); | |
+ $parent = $tree->getParent(5); | |
$ret = $tree->move(5, 5); | |
$tree->setup(); | |
@@ -61,7 +61,8 @@ | |
$this->fail('Expected TRUE but got a ' . gettype($ret)); | |
} | |
- $this->assertEquals($parentId, $tree->getParentId(5)); | |
+ $parent1 = $tree->getParent(5); | |
+ $this->assertEquals($parent['id'], $parent1['id']); | |
} | |
function test_MemoryMDBnestedNoAction() | |
@@ -72,7 +73,7 @@ | |
$tree = $this->getMemoryMDBnested(); | |
// $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- $parentId = $tree->getParentId(5); | |
+ $parent = $tree->getParent(5); | |
$ret = $tree->move(5, 5); | |
$tree->setup(); | |
@@ -83,7 +84,8 @@ | |
$this->fail('Expected TRUE but got a ' . gettype($ret)); | |
} | |
- $this->assertEquals($parentId, $tree->getParentId(5)); | |
+ $parent1 = $tree->getParent(5); | |
+ $this->assertEquals($parent['id'], $parent1['id']); | |
} | |
// do this for XML | |
@@ -92,10 +94,10 @@ | |
// do this for DBsimple | |
- // do this for DynamicDBnested | |
- function test_DynamicDBnested() | |
+ // do this for DynamicSQLnested | |
+ function test_DynamicSQLnested() | |
{ | |
- $tree =& $this->getDynamicDBnested(); | |
+ $tree =& $this->getDynamicSQLnested(); | |
$ret = $tree->move(5, 1); | |
// Avoid PHPUnit exhausting memory if $ret is a large array or object. | |
@@ -106,34 +108,15 @@ | |
} | |
// and check if the move succeeded, by checking the new parentId | |
- $this->assertEquals(1, $tree->getParentId(5)); | |
+ $parent = $tree->getParent(5); | |
+ $this->assertEquals(1, $parent['id']); | |
} | |
- function test_DynamicMDBnested() | |
+ function test_DynamicSQLnestedNoAction() | |
{ | |
- if (!$this->has_mdb) { | |
- $this->markTestSkipped('MDB is not installed'); | |
- } | |
- | |
- $tree =& $this->getDynamicDBnested(); | |
- $ret = $tree->move(5, 1); | |
- | |
- // Avoid PHPUnit exhausting memory if $ret is a large array or object. | |
- if (is_bool($ret)) { | |
- $this->assertTrue($ret); | |
- } else { | |
- $this->fail('Expected TRUE but got a ' . gettype($ret)); | |
- } | |
- | |
- // and check if the move succeeded, by checking the new parentId | |
- $this->assertEquals(1, $tree->getParentId(5)); | |
- } | |
- | |
- function test_DynamicDBnestedNoAction() | |
- { | |
- $tree =& $this->getDynamicDBnested(); | |
+ $tree =& $this->getDynamicSQLnested(); | |
// $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- $parentId = $tree->getParentId(5); | |
+ $parent = $tree->getParent(5); | |
$ret = $tree->move(5, 5); | |
// Avoid PHPUnit exhausting memory if $ret is a large array or object. | |
@@ -143,29 +126,9 @@ | |
$this->fail('Expected TRUE but got a ' . gettype($ret)); | |
} | |
- $this->assertEquals($parentId, $tree->getParentId(5)); | |
- } | |
- | |
- function test_DynamicMDBnestedNoAction() | |
- { | |
- if (!$this->has_mdb) { | |
- $this->markTestSkipped('MDB is not installed'); | |
- } | |
- | |
- $tree =& $this->getDynamicMDBnested(); | |
-// $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- $parentId = $tree->getParentId(5); | |
- $ret = $tree->move(5, 5); | |
- | |
- // Avoid PHPUnit exhausting memory if $ret is a large array or object. | |
- if (is_bool($ret)) { | |
- $this->assertTrue($ret); | |
- } else { | |
- $this->fail('Expected TRUE but got a ' . gettype($ret)); | |
- } | |
- | |
- $this->assertEquals($parentId, $tree->getParentId(5)); | |
- } | |
+ $parent1 = $tree->getParent(5); | |
+ $this->assertEquals($parent['id'], $parent1['id']); | |
+ } | |
} | |
?> | |
Property changes on: tests/moveTest.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.2 | |
+1.3 | |
Index: tests/getLevelTest.php | |
=================================================================== | |
--- tests/getLevelTest.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ tests/getLevelTest.php (.../trunk) (revision 321102) | |
@@ -1,7 +1,5 @@ | |
<?php | |
-// | |
// $Id$ | |
-// | |
require_once dirname(__FILE__) . '/TreeHelper.php'; | |
@@ -21,7 +19,7 @@ | |
$this->markTestSkipped('MDB is not installed'); | |
} | |
- $tree = $this->getMemoryMDBnested(); | |
+ $tree = $this->getMemoryMDBnested(); | |
$id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
$this->assertEquals(2, $tree->getLevel($id)); | |
} | |
@@ -32,26 +30,14 @@ | |
// do this for DBsimple | |
- // do this for DynamicDBnested | |
- function test_DynamicDBnested() | |
+ // do this for DynamicSQLnested | |
+ function test_DynamicSQLnested() | |
{ | |
- $tree =& $this->getDynamicDBnested(); | |
+ $tree =& $this->getDynamicSQLnested(); | |
// $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
$id = 5; | |
$this->assertEquals(2, $tree->getLevel($id)); | |
} | |
- | |
- function test_DynamicMDBnested() | |
- { | |
- if (!$this->has_mdb) { | |
- $this->markTestSkipped('MDB is not installed'); | |
- } | |
- | |
- $tree =& $this->getDynamicMDBnested(); | |
-// $id = $tree->getIdByPath('/Root/child 2/child 2_2'); | |
- $id = 5; | |
- $this->assertEquals(2, $tree->getLevel($id)); | |
- } | |
} | |
?> | |
Property changes on: tests/getLevelTest.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.2 | |
+1.3 | |
Index: tests | |
=================================================================== | |
--- tests (.../branches/Tree_0_3_0) (revision 321102) | |
+++ tests (.../trunk) (revision 321102) | |
Property changes on: tests | |
___________________________________________________________________ | |
Added: svn:ignore | |
## -0,0 +1 ## | |
+.getElementTest.php.swp | |
Index: TODO | |
=================================================================== | |
--- TODO (.../branches/Tree_0_3_0) (revision 321102) | |
+++ TODO (.../trunk) (revision 321102) | |
@@ -4,10 +4,52 @@ | |
use cached results. i.e. when calling getElement(2) three times, normally it would read | |
the data from the DB 3 times, but with a cache it could use cached results. | |
of course not cached permanently only for the current script life time | |
-- about Cache, add a per "transaction" cache. That means, when the users call a complex | |
+- about Cache, add a per "transaction" cache. That means, when the users call a complex | |
method (getIdByPath), cache the result during the read "transaction", lock? | |
-- setOption('columnNameMaps') doesnt work i.e. here | |
- $tree->setOption('columnNameMaps',array('myComment'=>'comment')); | |
- $tree->setOption('columnNameMaps',array('comment'=>'comment')); | |
- because we dont have the column name as the array key, so we cant overwrite it :-( | |
- this is really stupid | |
+ | |
+ http://www.phpguru.org/Tree2/ | |
+ * http://www.phpguru.org/article.php?ne_id=18 | |
+ http://cvs.iworks.at/cvs.php/Tree | |
+ http://wiki.iworks.at/index.php?area=Tree&page=HomePage | |
+ http://cvs.iworks.at/cvs.php/Gadget/Tree?login=2&rt=Gadget | |
+ Move to another architecture, talk to Mike and Lorenzo about joining in. | |
+ | |
+- Remove nodes recrusivly always. | |
+- Do not require the whole setup process after add/edit/remove/move/copy in memory | |
+ note sure tho what to do with memory <-> dynamic | |
+- because I removed things like parent, next, previous and such fromt the $data array | |
+ then I must fix _getElementId(removed) to cope with that and every other function related to this | |
+- Find a better way to deal with getParent and such when there is no result | |
+- remove buildStructure and add the level code to were I make the structure now and unset parent_id also in the data array | |
+- Add Transactions | |
+- New storage container approach | |
+- setData in all containers | |
+- Fully implement Array container | |
+- Fix structure thing, walk is having some issue, doesn't give errors anymore but there are issues | |
+- Fix getChildren | |
+- Enhance getAllChildren[ids] | |
+- Implement levels to getChildren | |
+- Reimplement get*Id and remove get* and have only one getNode or getData or what ever | |
+ | |
+Profile this whole thing with APD when I get it to work or xdebug | |
+ | |
+ | |
+Open your favourite browser, | |
+and google for "joe celko" and "nested set" | |
+ | |
+http://www.intelligententerprise.com/001020/celko.jhtml?_requestid=27476 | |
+http://www.dbmsmag.com/9603d06.html | |
+http://www.dbmsmag.com/9604d06.html | |
+http://www.ibase.ru/devinfo/DBMSTrees/sqltrees.html | |
+ | |
+Suggested books (both of them are excellent): | |
+http://www.amazon.com/exec/obidos/ASIN/0262032937/ | |
+http://www.amazon.com/exec/obidos/ASIN/1558609202/ | |
+ | |
+ | |
+http://www.msci.memphis.edu/~giri/7713/f99/l2/dferebee.htm | |
+ | |
+Good naming thign http://www.cross-browser.com/cbe/docs/core_om.html | |
+ | |
+http://www.entwickler.com/itr/online_artikel/psecom,id,387,nodeid,114.html | |
+file:///home/dufuz/Desktop/traer.html | |
Property changes on: TODO | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3 | |
+1.4 | |
Index: docs/Dynamic_DBnested.php | |
=================================================================== | |
--- docs/Dynamic_DBnested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/Dynamic_DBnested.php (.../trunk) (revision 321102) | |
@@ -1,51 +1,87 @@ | |
<?php | |
- // | |
- // $Id$ | |
- // | |
+// $Id$ | |
-//ini_set('include_path',realpath(dirname(__FILE__).'/../../').':'.realpath(dirname(__FILE__).'/../../../includes').':'.ini_get('include_path')); | |
+// use nested_tree.sql to build the db table | |
+ | |
ini_set('error_reporting', E_ALL); | |
- require_once 'Tree/Tree.php'; | |
+require_once 'Benchmark/Timer.php'; | |
+$timer = new Benchmark_Timer(); | |
+$timer->start(); | |
-# $tree = Tree::setupDynamic('DBnested' , 'mysql://root@localhost/tree_test' , array('table' => 'nestedTree')); | |
-# OR | |
- $tree = Tree::setup('Dynamic_DBnested' , 'mysql://root@localhost/tree_test' , array('table' => 'nestedTree')); | |
+require_once 'Tree/Tree.php'; | |
- $show[] = '$tree->getRoot()'; | |
- $show[] = '$tree->getElement(1)'; | |
- $show[] = '$tree->getChild(1)'; | |
- $show[] = '$tree->getPath(7)'; | |
- $show[] = '$tree->getPath(2)'; | |
- $show[] = '$tree->add(array("name"=>"c0") , 5 )'; | |
- $show[] = '$tree->remove( $res )'; // remove the last element that was added in the line before :-) | |
- $show[] = '$tree->getRight( 5 )'; | |
- $show[] = '$tree->getLeft( 5 )'; | |
- $show[] = '$tree->getChildren( 1 )'; | |
- $show[] = '$tree->getParent( 2 )'; | |
- $show[] = '$tree->getNext( 2 )'; | |
- $show[] = '$tree->getNext( 4 )'; | |
- $show[] = '$tree->getNext( 8 )'; | |
- $show[] = '$tree->getPrevious( 2 )'; | |
- $show[] = '$tree->getPrevious( 4 )'; | |
- $show[] = '$tree->getPrevious( 8 )'; | |
- $show[] = '$tree->getPreviousId( 8 )'; | |
+$config = array( | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => 'DB', | |
+ 'dsn' => 'mysql://root:hamstur@localhost/tree_test', | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => 'nestedTree', | |
+ 'order' => 'id', | |
+ 'fields' => array(), | |
+ ), | |
+); | |
- $show[] = '$tree->move( 4,3 )'; | |
+$tree =& Tree::factoryDynamic($config); | |
+$show[] = '$tree->getRoot()'; | |
+$show[] = '$tree->getElement(1)'; | |
+$show[] = '$tree->getChildren(1, true)'; | |
+$show[] = '$tree->getPath(7)'; | |
+$show[] = '$tree->getPath(2)'; | |
+$show[] = '$tree->add(array("name"=>"c0") , 5 )'; | |
+$show[] = '$tree->remove( $res )'; // remove the last element that was added in the line before :-) | |
+$show[] = '$tree->getRight( 5 )'; | |
+$show[] = '$tree->getLeft( 5 )'; | |
+$show[] = '$tree->getChildren( 1 )'; | |
+$show[] = '$tree->getParent( 2 )'; | |
+$show[] = '$tree->nextSibling( 2 )'; | |
+$show[] = '$tree->nextSibling( 4 )'; | |
+$show[] = '$tree->nextSibling( 8 )'; | |
+$show[] = '$tree->previousSibling( 2 )'; | |
+$show[] = '$tree->previousSibling( 4 )'; | |
+$show[] = '$tree->previousSibling( 8 )'; | |
- foreach($show as $aRes) { | |
- echo "<b>$aRes</b><br>"; | |
- eval("\$res=".$aRes.';'); | |
- if ($res == false) { | |
- print "false"; | |
- } else { | |
- print_r($res); | |
- } | |
- echo '<br><br>'; | |
+$show[] = '$tree->move( 4,3 )'; | |
+ | |
+ | |
+foreach ($show as $aRes) { | |
+ echo "<strong>$aRes</strong><br />"; | |
+ eval("\$res=".$aRes.';'); | |
+ if ($res == false) { | |
+ print "false"; | |
+ } else { | |
+ echo '<pre>'; | |
+ print_r($res); | |
+ echo '</pre>'; | |
} | |
+ echo '<br /><br />'; | |
+} | |
+$timer->stop(); | |
+$timer->display(); | |
+$timer = new Benchmark_Timer(); | |
+$timer->start(); | |
+ | |
+$root = $tree->getRoot(); | |
+recursive($root['id']); | |
+ | |
+$timer->stop(); | |
+$timer->display(); | |
+ | |
+function recursive($id) | |
+{ | |
+ global $tree; | |
+ $blah = $tree->getChildren($id); | |
+ foreach ($blah as $row) { | |
+ echo str_repeat('-', $tree->getLevel($row['id']) - 1) . $row['id'].'<br />'; | |
+ recursive($row['id']); | |
+ } | |
+} | |
?> | |
<a href="http://research.calacademy.org/taf/proceedings/ballew/sld029.htm">the tree structure visualisation</a> | |
Property changes on: docs/Dynamic_DBnested.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3 | |
+1.4 | |
Index: docs/Memory_MDBnested.php | |
=================================================================== | |
--- docs/Memory_MDBnested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/Memory_MDBnested.php (.../trunk) (revision 321102) | |
@@ -1,58 +1,14 @@ | |
<?php | |
// $Id$ | |
-ini_set('error_reporting',E_ALL); | |
+include_once 'funcs.php'; | |
- /** | |
- * this is a helper function, so i dont have to write so many prints :-) | |
- * @param array $para the result returned by some method, that will be dumped | |
- * @param string $string the explaining string | |
- */ | |
- function dumpHelper($para, $string = '', $addArray = false) | |
- { | |
- global $tree, $element; | |
- if ($addArray) { | |
- eval( "\$res=array(".$para.');' ); | |
- } else { | |
- eval( "\$res=".$para.';' ); | |
- } | |
- echo '<b>'.$para.' </b><i><u><span style="color: #008000">'.$string.'</span></u></i><br />'; | |
- // this method dumps to the screen, since print_r or var_dump dont | |
- // work too good here, because the inner array is recursive | |
- // well, it looks ugly but one can see what is meant :-) | |
- $tree->varDump($res); | |
- echo '<br />'; | |
- | |
- } | |
- | |
- /** | |
- * dumps the entire structure nicely | |
- * @param string $string the explaining string | |
- */ | |
- function dumpAllNicely($string = '') | |
- { | |
- global $tree; | |
- | |
- echo '<i><u><span style="color: #008000">'.$string.'</span></u></i><br />'; | |
- $all = $tree->getNode(); // get the entire structure sorted as the tree is, so we can simply foreach through it and show it | |
- foreach($all as $aElement) { | |
- for ($i = 0; $i < $aElement['level']; $i++) { | |
- echo ' '; | |
- } | |
- echo '<span style="color: red">'.$aElement['name'].'</span> ===> '; | |
- $tree->varDump(array($aElement)); | |
- } | |
- echo '<br />'; | |
- | |
- } | |
- | |
- | |
/* | |
use this to build the db table | |
- CREATE TABLE Memory_Nested_MDB ( | |
+ CREATE TABLE Memory_nestedTree ( | |
id int(11) NOT NULL default '0', | |
name varchar(255) NOT NULL default '', | |
l int(11) NOT NULL default '0', | |
@@ -62,7 +18,6 @@ | |
PRIMARY KEY (id) | |
); | |
- | |
This example demonstrates how to manage trees | |
that are saved in a DB, it uses a very simple | |
DB-structure, not nested trees (ok, that sucks, but it can be implemented :-) ) | |
@@ -78,10 +33,6 @@ | |
require_once 'Tree/Tree.php'; | |
// define the DB-table where the data shall be read from | |
- $options = array('table' => 'Memory_Nested_MDB' | |
- ,'whereAddOn' => "comment=''" | |
- ); | |
- | |
// calling 'setupMemory' means to retreive a class, which works on trees, | |
// that are temporarily stored in the memory, in an array | |
// this means the entire tree is available at all time !!! | |
@@ -92,10 +43,23 @@ | |
// use the nested DB schema, which is actually implemented in Dynamic/DBnested | |
// the class Memory/DBnested is only kind of a wrapper to read the entire tree | |
// and let u work on it, which to use should be chosen on case by case basis | |
- $tree = Tree::setupMemory('MDBnested', | |
- 'mysql://root@localhost/tree_test', // the DSN | |
- $options); // pass the options we had assigned up there | |
+$config = array( | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => 'MDB', | |
+ 'dsn' => 'mysql://root:hamstur@localhost/tree_test', | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => 'nestedTree', | |
+ 'order' => 'id', | |
+ 'fields' => array(), | |
+ 'whereAddOn' => "comment=''" | |
+ ), | |
+); | |
+$tree =& Tree::factoryMemory($config); // pass the options we had assigned up there | |
+ | |
// add a new root element in the tree | |
$rootId = $tree->add(array('name' => 'myElement')); | |
@@ -119,7 +83,7 @@ | |
// you can also use: $tree->data[$id]['parent'] | |
$id = $tree->getIdByPath('myElement'); | |
- dumpHelper('$tree->getChild('.$id.')' , 'dump the child of "myElement"' , true); | |
+ dumpHelper('$tree->getChildren('.$id.', true)' , 'dump the child of "myElement"' , true); | |
// you can also use: $tree->data[$id]['child'] | |
$id = $tree->getIdByPath('myElement'); | |
@@ -127,11 +91,11 @@ | |
// you can also use: $tree->data[$id]['children'] | |
$id = $tree->getIdByPath('myElement/subElement'); | |
- dumpHelper('$tree->getNext('.$id.')' , 'dump the "next" of "myElement/subElement"' , true); | |
+ dumpHelper('$tree->nextSibling('.$id.')' , 'dump the "next" of "myElement/subElement"' , true); | |
// you can also use: $tree->data[$id]['next'] | |
$id = $tree->getIdByPath('myElement/anotherSubElement'); | |
- dumpHelper('$tree->getPrevious('.$id.')' , 'dump the "previous" of "myElement/anotherSubElement"' , true); | |
+ dumpHelper('$tree->previousSibling('.$id.')' , 'dump the "previous" of "myElement/anotherSubElement"' , true); | |
// you can also use: $tree->data[$id]['previous'] | |
$id = $tree->getIdByPath('myElement'); | |
@@ -141,18 +105,18 @@ | |
$id = $tree->getIdByPath('myElement'); | |
$element = $tree->data[$id]['child']['next']; // refer to the second child of 'myElement' | |
dumpHelper('$element[\'id\']' , 'demo2 of using the internal array, for referencing tree-nodes, see the code'); | |
-/* | |
+ | |
$id = $tree->getIdByPath('myElement/anotherSubElement'); | |
- $tree->move( $id , 0 ); | |
+ $tree->move($id , 0); | |
$tree->setup(); // rebuild the structure again, since we had changed it | |
dumpAllNicely( 'dump all, after "myElement/anotherSubElement" was moved under the root' ); | |
$moveId = $tree->getIdByPath('myElement'); | |
$id = $tree->getIdByPath('anotherSubElement'); | |
- $tree->move( $moveId , $id ); | |
+ $tree->move($moveId , $id); | |
$tree->setup(); // rebuild the structure again, since we had changed it | |
dumpAllNicely( 'dump all, after "myElement" was moved under the "anotherSubElement"' ); | |
-*/ | |
+ | |
$tree->setRemoveRecursively(true); | |
$tree->remove($rootId); | |
echo '<span style="color: red">ALL ELEMENTS HAVE BEEN REMOVED (uncomment this part to keep them in the DB after running this test script)</span>'; | |
Property changes on: docs/Memory_MDBnested.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.1 | |
+1.2 | |
Index: docs/doc.sxw | |
=================================================================== | |
Cannot display: file marked as a binary type. | |
svn:mime-type = application/octet-stream | |
Index: docs/doc.sxw | |
=================================================================== | |
--- docs/doc.sxw (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/doc.sxw (.../trunk) (revision 321102) | |
Property changes on: docs/doc.sxw | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.1 | |
+1.2 | |
Index: docs/Memory_MDBsimple.php | |
=================================================================== | |
--- docs/Memory_MDBsimple.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/Memory_MDBsimple.php (.../trunk) (revision 321102) | |
@@ -1,63 +1,16 @@ | |
<?php | |
- // | |
- // $Id$ | |
- // | |
+// $Id$ | |
-//ini_set('include_path',realpath(dirname(__FILE__).'/../../').':'.realpath(dirname(__FILE__).'/../../../includes').':'.ini_get('include_path')); | |
-//ini_set('error_reporting',E_ALL); | |
+include_once 'funcs.php'; | |
- /** | |
- * this is a helper function, so i dont have to write so many prints :-) | |
- * @param array $para the result returned by some method, that will be dumped | |
- * @param string $string the explaining string | |
- */ | |
- function dumpHelper($para, $string = '', $addArray = false) | |
- { | |
- global $tree,$element; | |
- if ($addArray) { | |
- eval("\$res=array(".$para.');'); | |
- } else { | |
- eval("\$res=".$para.';'); | |
- } | |
- echo '<b>' . $para . ' </b><i><u><font color="#008000">' . $string . '</font></u></i><br>'; | |
- // this method dumps to the screen, since print_r or var_dump dont | |
- // work too good here, because the inner array is recursive | |
- // well, it looks ugly but one can see what is meant :-) | |
- $tree->varDump($res); | |
- echo '<br>'; | |
- | |
- } | |
- | |
- /** | |
- * dumps the entire structure nicely | |
- * @param string $string the explaining string | |
- */ | |
- function dumpAllNicely($string = '') | |
- { | |
- global $tree; | |
- | |
- echo '<i><u><font color="#008000">' . $string . '</font></u></i><br>'; | |
- $all = $tree->getNode(); // get the entire structure sorted as the tree is, so we can simply foreach through it and show it | |
- foreach($all as $aElement) { | |
- for ($i = 0; $i < $aElement['level']; $i++) { | |
- echo ' '; | |
- } | |
- echo $aElement['name'].' ===> '; | |
- $tree->varDump(array($aElement)); | |
- } | |
- echo '<br>'; | |
- | |
- } | |
- | |
- | |
/* | |
use this to build the db table | |
CREATE TABLE test_tree ( | |
id int(11) NOT NULL auto_increment, | |
- parentId int(11) NOT NULL default '0', | |
+ parent int(11) NOT NULL default '0', | |
name varchar(255) NOT NULL default '', | |
PRIMARY KEY (id) | |
) | |
@@ -74,39 +27,71 @@ | |
i will try to demonstrate (all of) them | |
*/ | |
+ require_once 'MDB.php'; | |
+ require_once 'Benchmark/Timer.php'; | |
+ $timer = new Benchmark_Timer(); | |
+ $timer->start(); | |
+ | |
require_once 'Tree/Tree.php'; | |
// define the DB-table where the data shall be read from | |
- $options = array('table' => 'test_tree', | |
- 'order' => 'id' // when reading the data from the db sort them by id, this is only for ensuring | |
- // for 'getNext' of "myElement/subElement" in this example to find "myElement/anotherSubElement" | |
- // you can simply sort it by "name" and it would be in alphabetical order | |
- ); | |
- | |
+ // when reading the data from the db sort them by id, this is only for ensuring | |
+ // for 'getNext' of "myElement/subElement" in this example to find "myElement/anotherSubElement" | |
+ // you can simply sort it by "name" and it would be in alphabetical order | |
// calling 'setupMemory' means to retreive a class, which works on trees, | |
// that are temporarily stored in the memory, in an array | |
// this means the entire tree is available at all time | |
// consider the resource usage and it's not to suggested to work | |
// on huge trees (upto 1000 elements it should be ok, depending on your environment and requirements) | |
// using 'setupMemory' | |
- $tree = Tree::setupMemory('DBsimple', // use the simple DB schema | |
- 'mysql://root@localhost/tree_test', // the DSN | |
- $options); // pass the options we had assigned up there | |
+ $config = array( | |
+ 'type' => 'Simple', | |
+ 'storage' => array( | |
+ 'name' => 'MDB2', | |
+ 'dsn' => 'mysql://root:hamstur@localhost/tree_test', | |
+ // 'connection' => $db | |
+ ), | |
+ 'options' => array( | |
+ 'table' => 'test_tree', | |
+ 'order' => 'id', | |
+ 'fields' => array(), | |
+ ), | |
+ ); | |
+ $tree =& Tree::factoryMemory($config); | |
+ | |
+ $timer->setMarker('Marker 1'); | |
// add a new root element in the tree | |
- $parentId = $tree->add(array('name' => 'myElement')); | |
+ #$parentId = $tree->add(array('name' => 'myElement')); | |
// add an element under the new element we added | |
- $id = $tree->add(array('name' => 'subElement') , $parentId ); | |
+ #$id = $tree->add(array('name' => 'subElement'), $parentId); | |
// add another element under the parent element we added | |
- $id = $tree->add(array('name' => 'anotherSubElement') , $parentId ); | |
+ #$id = $tree->add(array('name' => 'anotherSubElement'), $parentId); | |
+ #$id = $tree->add(array('name' => 'anotherSubElement'), $id); | |
+$id = 0; | |
// call 'setup', to build the inner array, so we can work on the structure using the | |
// given methods | |
$tree->setup(); | |
+ $timer->setMarker('Marker 2'); | |
+echo '<pre>'; print_r($tree->children); echo '</pre>'; | |
+ | |
+$foo = $tree->getPath(14); | |
+echo '<pre>'; print_r($foo); echo '</pre>'; | |
+ | |
+$count = count($foo) - 1; | |
+foreach ($foo as $k => $row) { | |
+ echo '<a href="?go=forum&id=' . $row['id'] . '">' . $row['name'] . '</a>'; | |
+ if ($k < $count) { | |
+ echo ' > '; | |
+ } | |
+} | |
+echo '<br />'; | |
+ | |
dumpAllNicely('dump all after creation'); | |
// get the path of the last inserted element | |
@@ -114,45 +99,41 @@ | |
print "tree->getIdByPath('myElement/subElement')=".$id = $tree->getIdByPath('myElement/subElement'); | |
dumpHelper('$tree->getParent('.$id.')' , 'dump the parent of "myElement/subElement"' , true); | |
- // you can also use: $tree->data[$id]['parent'] | |
+ // you can also use: $tree->data[$id]['parent_id'] | |
$id = $tree->getIdByPath('myElement'); | |
- dumpHelper('$tree->getChild('.$id.')' , 'dump the child of "myElement"' , true); | |
- // you can also use: $tree->data[$id]['child'] | |
+ dumpHelper('$tree->getChildren('.$id.', true)' , 'dump the child of "myElement"', true); | |
$id = $tree->getIdByPath('myElement'); | |
dumpHelper('$tree->getChildren('.$id.')' , 'dump the children of "myElement"'); | |
- // you can also use: $tree->data[$id]['children'] | |
$id = $tree->getIdByPath('myElement/subElement'); | |
- dumpHelper('$tree->getNext('.$id.')' , 'dump the "next" of "myElement/subElement"' , true); | |
- // you can also use: $tree->data[$id]['next'] | |
+ dumpHelper('$tree->nextSibling('.$id.')' , 'dump the "next" of "myElement/subElement"' , true); | |
+ // you can also use: $tree->data[$id]['nextId'] | |
$id = $tree->getIdByPath('myElement/anotherSubElement'); | |
- dumpHelper('$tree->getPrevious('.$id.')' , 'dump the "previous" of "myElement/anotherSubElement"' , true); | |
- // you can also use: $tree->data[$id]['previous'] | |
+ dumpHelper('$tree->prevSibling('.$id.')' , 'dump the "previous" of "myElement/anotherSubElement"' , true); | |
+ // you can also use: $tree->data[$id]['previousId'] | |
- $id = $tree->getIdByPath('myElement'); | |
- $element = $tree->data[$id]['child']['next']['parent']; // refer to yourself again, in a very complicated way :-) | |
- dumpHelper('$element[\'id\']' , 'demo of using the internal array, for referencing tree-nodes, see the code'); | |
- | |
- $id = $tree->getIdByPath('myElement'); | |
- $element = $tree->data[$id]['child']['next']; // refer to the second child of 'myElement' | |
- dumpHelper('$element[\'id\']' , 'demo2 of using the internal array, for referencing tree-nodes, see the code'); | |
- | |
$id = $tree->getIdByPath('myElement/anotherSubElement'); | |
- $tree->move($id , 0); | |
- $tree->setup(); // rebuild the structure again, since we had changed it | |
+ #$tree->move($id , 0); | |
+ #$tree->setup(); // rebuild the structure again, since we had changed it | |
dumpAllNicely( 'dump all, after "myElement/anotherSubElement" was moved under the root' ); | |
- $moveId = $tree->getIdByPath('myElement'); | |
+ #$moveId = $tree->getIdByPath('myElement'); | |
$id = $tree->getIdByPath('anotherSubElement'); | |
- $tree->move( $moveId , $id ); | |
- $tree->setup(); // rebuild the structure again, since we had changed it | |
- dumpAllNicely('dump all, after "myElement" was moved under the "anotherSubElement"'); | |
+ #$tree->move($moveId , $id); | |
+ #$tree->setup(); // rebuild the structure again, since we had changed it | |
+ #dumpAllNicely('dump all, after "myElement" was moved under the "anotherSubElement"'); | |
- $tree->setRemoveRecursively(true); | |
- $tree->remove(0); | |
- echo '<font color="red">ALL ELEMENTS HAVE BEEN REMOVED (uncomment this part to keep them in the DB after running this test script)</font>'; | |
+ //$tree->setRemoveRecursively(true); | |
+ //$tree->remove(0); | |
+ //echo '<font color="red">ALL ELEMENTS HAVE BEEN REMOVED (uncomment this part to keep them in the DB after running this test script)</font>'; | |
+$timer->stop(); | |
+$timer->display(); | |
+ | |
+$foo = $tree->getRoot();var_dump($foo); | |
+#$blah = $tree->getChildren($foo); var_dump($blah); | |
+$aha = $tree->getBranch(); var_dump($aha); | |
?> | |
Property changes on: docs/Memory_MDBsimple.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.1 | |
+1.2 | |
Index: docs/TreeView/index.php | |
=================================================================== | |
--- docs/TreeView/index.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/TreeView/index.php (.../trunk) (revision 321102) | |
@@ -1,22 +1,20 @@ | |
<?php | |
- // | |
- // $Id$ | |
- // | |
-ini_set('include_path',realpath(dirname(__FILE__).'/../../../').':'.realpath(dirname(__FILE__).'/../../../../includes').':'.ini_get('include_path')); | |
-ini_set('error_reporting',E_ALL); | |
+// $Id$ | |
+ini_set('error_reporting', E_ALL); | |
+ | |
################################################## | |
# | |
# init template engine | |
# | |
// you need the template class from http://sf.net/projects/simpltpl | |
- if (!@include('HTML/Template/Xipe.php')) { | |
+ if (!@include 'HTML/Template/Xipe.php') { | |
print 'sorry, you need the template class PEAR::HTML_Template_Xipe<br>'. | |
'or if i have time i put the examples <a href="http://os.visionp.de/">here online</a>'; | |
die(); | |
} | |
- require_once('HTML/Template/Xipe/Filter/TagLib.php'); | |
- $options = array( 'templateDir' => dirname(__FILE__) ); | |
+ require_once 'HTML/Template/Xipe/Filter/TagLib.php'; | |
+ $options = array('templateDir' => dirname(__FILE__)); | |
$tpl = new HTML_Template_Xipe($options); | |
@@ -24,56 +22,53 @@ | |
# | |
# actual tree stuff, using Dynamic_DBnested | |
# | |
- require_once('Tree/Tree.php'); | |
- $tree = Tree::setup( 'Dynamic_DBnested' , 'mysql://root@localhost/test' , array('table'=>'Tree_Nested') ); | |
+ require_once 'Tree/Tree.php'; | |
+ $tree = Tree::setup('Dynamic_DBnested' , 'mysql://root@localhost/tree_test' , array('table' => 'Tree_Nested')); | |
- if( @$_REQUEST['action_add'] ) | |
- { | |
+ if (@$_REQUEST['action_add']) { | |
$methodCall = "tree->add( {$_REQUEST['newData']} , {$_REQUEST['parentId']} , {$_REQUEST['prevId']} )"; | |
$result = $tree->add( $_REQUEST['newData'] , $_REQUEST['parentId'] , $_REQUEST['prevId'] ); | |
} | |
- if( @$_REQUEST['action_remove'] ) | |
- { | |
+ if (@$_REQUEST['action_remove']) { | |
$methodCall = "$tree->remove( {$_REQUEST['removeId']} )"; | |
$result = $tree->remove( $_REQUEST['removeId'] ); | |
} | |
- if( @$_REQUEST['action_update'] ) | |
- { | |
+ if (@$_REQUEST['action_update']) { | |
$methodCall = "tree->update( {$_REQUEST['updateId']} , {$_REQUEST['updateData']} )"; | |
$result = $tree->update( $_REQUEST['updateId'] , $_REQUEST['updateData'] ); | |
} | |
- if( @$_REQUEST['action_move'] ) | |
- { | |
+ if (@$_REQUEST['action_move']) { | |
$methodCall = "tree->move( {$_REQUEST['move_id']} , {$_REQUEST['move_newParentId']} , {$_REQUEST['move_newPrevId']} )"; | |
$result = $tree->move( $_REQUEST['move_id'] , $_REQUEST['move_newParentId'] , $_REQUEST['move_newPrevId'] ); | |
} | |
$methodFailed = false; | |
- if( @PEAR::isError($result) ) | |
+ if (@PEAR::isError($result)) { | |
$methodFailed = true; | |
+ } | |
$fid = @$_REQUEST['fid']; | |
- if( !$fid ) | |
+ if (!$fid) { | |
$fid = $tree->getRootId(); | |
+ } | |
+ $path = $tree->getPath($fid); | |
+ $children = $tree->getChildren($fid); | |
- $path = $tree->getPath( $fid ); | |
- $children = $tree->getChildren( $fid ); | |
- | |
################################################## | |
# | |
# actual tree stuff to show the entire tree using Memory_DBnested | |
# | |
- require_once('Tree/Tree.php'); | |
- $memTree = Tree::setup( 'Memory_DBnested' , 'mysql://root@localhost/test' , | |
- array('table'=>'Tree_Nested') ); | |
+ require_once 'Tree/Tree.php'; | |
+ $memTree = Tree::setup('Memory_DBnested' , 'mysql://root@localhost/test' , | |
+ array('table'=>'Tree_Nested')); | |
$memTree->setup(); | |
$entireTree = $memTree->getNode(); | |
$treeDepth = $memTree->getDepth(); | |
$tpl->compile('index.tpl'); | |
- include($tpl->compiledTemplate); | |
+ include $tpl->compiledTemplate; | |
?> | |
Property changes on: docs/TreeView/index.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3 | |
+1.4 | |
Index: docs/Dynamic_MDBnested.php | |
=================================================================== | |
--- docs/Dynamic_MDBnested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/Dynamic_MDBnested.php (.../trunk) (revision 321102) | |
@@ -1,51 +1,61 @@ | |
<?php | |
- // | |
- // $Id$ | |
- // | |
+// $Id$ | |
-//ini_set('include_path',realpath(dirname(__FILE__).'/../../').':'.realpath(dirname(__FILE__).'/../../../includes').':'.ini_get('include_path')); | |
-//ini_set('error_reporting',E_ALL); | |
+// use nested_tree.sql to build the db table | |
- require_once 'Tree/Tree.php'; | |
+ini_set('error_reporting', E_ALL); | |
-# $tree = Tree::setupDynamic('MDBnested' , 'mysql://root@localhost/tree_test' , array('table' => 'nestedTree')); | |
-# OR | |
- $tree = Tree::setup('Dynamic_MDBnested' , 'mysql://root@localhost/tree_test' , array('table' => 'nestedTree')); | |
+require_once 'Tree/Tree.php'; | |
- $show[] = '$tree->getRoot()'; | |
- $show[] = '$tree->getElement( 1 )'; | |
- $show[] = '$tree->getChild( 1 )'; | |
- $show[] = '$tree->getPath( 7 )'; | |
- $show[] = '$tree->getPath( 2 )'; | |
- $show[] = '$tree->add( array("name"=>"c0") , 5 )'; | |
- $show[] = '$tree->remove( $res )'; // remove the last element that was added in the line before :-) | |
- $show[] = '$tree->getRight( 5 )'; | |
- $show[] = '$tree->getLeft( 5 )'; | |
- $show[] = '$tree->getChildren( 1 )'; | |
- $show[] = '$tree->getParent( 2 )'; | |
- $show[] = '$tree->getNext( 2 )'; | |
- $show[] = '$tree->getNext( 4 )'; | |
- $show[] = '$tree->getNext( 8 )'; | |
- $show[] = '$tree->getPrevious( 2 )'; | |
- $show[] = '$tree->getPrevious( 4 )'; | |
- $show[] = '$tree->getPrevious( 8 )'; | |
- $show[] = '$tree->getPreviousId( 8 )'; | |
+$config = array( | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => 'MDB', | |
+ 'dsn' => 'mysql://root:hamstur@localhost/tree_test', | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => 'nestedTree', | |
+ 'order' => 'id', | |
+ 'fields' => array(), | |
+ ), | |
+); | |
- $show[] = '$tree->move( 4,3 )'; | |
+$tree =& Tree::factoryDynamic($config); | |
+$show[] = '$tree->getRoot()'; | |
+$show[] = '$tree->getElement( 1 )'; | |
+$show[] = '$tree->getChildren(1, true)'; | |
+$show[] = '$tree->getPath( 7 )'; | |
+$show[] = '$tree->getPath( 2 )'; | |
+// $show[] = '$tree->add( array("name"=>"c0") , 5 )'; | |
+// $show[] = '$tree->remove( $res )'; // remove the last element that was added in the line before :-) | |
+$show[] = '$tree->getRight( 5 )'; | |
+$show[] = '$tree->getLeft( 5 )'; | |
+$show[] = '$tree->getChildren( 1 )'; | |
+$show[] = '$tree->getParent( 2 )'; | |
+$show[] = '$tree->nextSibling( 2 )'; | |
+$show[] = '$tree->nextSibling( 4 )'; | |
+$show[] = '$tree->nextSibling( 8 )'; | |
+$show[] = '$tree->previousSibling( 2 )'; | |
+$show[] = '$tree->previousSibling( 4 )'; | |
+$show[] = '$tree->previousSibling( 8 )'; | |
- foreach($show as $aRes) { | |
- echo "<b>$aRes</b><br>"; | |
- eval("\$res=".$aRes.';'); | |
- if ($res == false) { | |
- print "false"; | |
- } else { | |
- print_r($res); | |
- } | |
- echo '<br><br>'; | |
- } | |
+$show[] = '$tree->move( 4,3 )'; | |
+foreach ($show as $aRes) { | |
+ echo "<strong>$aRes</strong><br />"; | |
+ eval("\$res=".$aRes.';'); | |
+ if ($res == false) { | |
+ print "false"; | |
+ } else { | |
+ echo '<pre>'; | |
+ print_r($res); | |
+ echo '</pre>'; | |
+ } | |
+ echo '<br /><br />'; | |
+} | |
?> | |
<a href="http://research.calacademy.org/taf/proceedings/ballew/sld029.htm">the tree structure visualisation</a> | |
Property changes on: docs/Dynamic_MDBnested.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.1 | |
+1.2 | |
Index: docs/nested_tree.sql | |
=================================================================== | |
--- docs/nested_tree.sql (.../branches/Tree_0_3_0) (revision 0) | |
+++ docs/nested_tree.sql (.../trunk) (revision 321102) | |
@@ -0,0 +1,44 @@ | |
+# | |
+# Table structure for table `nestedTree` | |
+# | |
+ | |
+CREATE TABLE nestedTree ( | |
+ id int(11) NOT NULL default '0', | |
+ name varchar(255) NOT NULL default '', | |
+ l int(11) NOT NULL default '0', | |
+ r int(11) NOT NULL default '0', | |
+ parent int(11) NOT NULL default '0', | |
+ comment varchar(255) NOT NULL default '', | |
+ PRIMARY KEY (id) | |
+) TYPE=MyISAM; | |
+ | |
+# | |
+# Dumping data for table `nestedTree` | |
+# | |
+ | |
+INSERT INTO nestedTree VALUES (1, 'Root', 1, 24, 0, ''); | |
+INSERT INTO nestedTree VALUES (2, 'A1', 2, 11, 1, ''); | |
+INSERT INTO nestedTree VALUES (3, 'A2', 12, 23, 1, ''); | |
+INSERT INTO nestedTree VALUES (4, 'A3', 13, 16, 3, ''); | |
+INSERT INTO nestedTree VALUES (5, 'B1', 3, 10, 2, ''); | |
+INSERT INTO nestedTree VALUES (6, 'B2', 17, 18, 3, ''); | |
+INSERT INTO nestedTree VALUES (7, 'B3', 19, 22, 3, ''); | |
+INSERT INTO nestedTree VALUES (8, 'C1', 20, 21, 7, ''); | |
+INSERT INTO nestedTree VALUES (9, 'B4', 14, 15, 4, ''); | |
+# -------------------------------------------------------- | |
+ | |
+# | |
+# Table structure for table `nestedTree_seq` | |
+# | |
+ | |
+CREATE TABLE nestedTree_seq ( | |
+ id int(10) unsigned NOT NULL auto_increment, | |
+ PRIMARY KEY (id) | |
+) TYPE=MyISAM; | |
+ | |
+# | |
+# Dumping data for table `nestedTree_seq` | |
+# | |
+ | |
+INSERT INTO nestedTree_seq VALUES (3); | |
+ | |
Property changes on: docs/nested_tree.sql | |
___________________________________________________________________ | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Index: docs/speed_test/setup.php | |
=================================================================== | |
--- docs/speed_test/setup.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ docs/speed_test/setup.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,44 @@ | |
+<?php | |
+require_once 'Tree/Tree.php'; | |
+ | |
+$config = array( | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => 'MDB2', | |
+ 'dsn' => 'mysql://root:hamstur@localhost/tree_test', | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => 'nestedTree1', | |
+ 'order' => 'id', | |
+ 'fields' => array(), | |
+ ), | |
+); | |
+ | |
+$tree =& Tree::factoryDynamic($config); | |
+ | |
+ | |
+$tree->add(array('name' => 'c0') , 0); | |
+$tree->add(array('name' => 'c1') , 1); | |
+$tree->add(array('name' => 'c2') , 2); | |
+$tree->add(array('name' => 'c3') , 3); | |
+ | |
+$tree->add(array('name' => 'c0') , 4); | |
+$tree->add(array('name' => 'c1') , 5); | |
+$tree->add(array('name' => 'c2') , 6); | |
+$tree->add(array('name' => 'c3') , 7); | |
+ | |
+$tree->add(array('name' => 'c0') , 8); | |
+$tree->add(array('name' => 'c1') , 9); | |
+$tree->add(array('name' => 'c2') , 10); | |
+$tree->add(array('name' => 'c3') , 11); | |
+ | |
+$tree->add(array('name' => 'c0') , 12); | |
+$tree->add(array('name' => 'c1') , 13); | |
+$tree->add(array('name' => 'c2') , 14); | |
+$tree->add(array('name' => 'c3') , 15); | |
+ | |
+$tree->add(array('name' => 'c0') , 16); | |
+$tree->add(array('name' => 'c1') , 17); | |
+$tree->add(array('name' => 'c2') , 18); | |
+$tree->add(array('name' => 'c3') , 19); | |
\ No newline at end of file | |
Property changes on: docs/speed_test/setup.php | |
___________________________________________________________________ | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Index: docs/speed_test/speed.php | |
=================================================================== | |
--- docs/speed_test/speed.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ docs/speed_test/speed.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,35 @@ | |
+<?php | |
+require_once 'Tree/Tree.php'; | |
+ | |
+$config = array( | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => 'MDB2', | |
+ 'dsn' => 'mysql://root:hamstur@localhost/tree_test', | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => 'nestedTree1', | |
+ 'order' => 'id', | |
+ 'fields' => array(), | |
+ ), | |
+); | |
+ | |
+$tree =& Tree::factoryMemory($config); | |
+$tree->setup(); | |
+ | |
+$root = $tree->getRoot(); | |
+ | |
+echo str_repeat('-', $tree->getLevel($root['id'])) . $root['id'] . ' (parent: ' . $root['parent_id'] . ')<br />'; | |
+recursive($root['id']); | |
+ | |
+// Usually it's a good idea to do -1 on each level since there can only be one root node | |
+function recursive($id) | |
+{ | |
+ global $tree; | |
+ $blah = $tree->getChildren($id); | |
+ foreach ($blah as $row) { | |
+ echo str_repeat('-', $tree->getLevel($row['id'])) . $row['id'] . ' (parent: ' . $row['parent_id'] . ')<br />'; | |
+ recursive($row['id']); | |
+ } | |
+} | |
\ No newline at end of file | |
Property changes on: docs/speed_test/speed.php | |
___________________________________________________________________ | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Index: docs/funcs.php | |
=================================================================== | |
--- docs/funcs.php (.../branches/Tree_0_3_0) (revision 0) | |
+++ docs/funcs.php (.../trunk) (revision 321102) | |
@@ -0,0 +1,48 @@ | |
+<?php | |
+// $Id$ | |
+ | |
+ini_set('error_reporting', E_ALL); | |
+ | |
+/** | |
+* this is a helper function, so i dont have to write so many prints :-) | |
+* @param array $para the result returned by some method, that will be dumped | |
+* @param string $string the explaining string | |
+*/ | |
+function dumpHelper($para, $string = '', $addArray = false) | |
+{ | |
+ global $tree, $element; | |
+ | |
+ if ($addArray) { | |
+ eval("\$res=array(".$para.');'); | |
+ } else { | |
+ eval("\$res=".$para.';'); | |
+ } | |
+ echo '<strong>' . $para . ' </strong><i><u><span style="color: #008000;">' . $string . '</span></u></i><br>'; | |
+ // this method dumps to the screen, since print_r or var_dump dont | |
+ // work too good here, because the inner array is recursive | |
+ // well, it looks ugly but one can see what is meant :-) | |
+ $tree->varDump($res); | |
+ echo '<br />'; | |
+ | |
+} | |
+ | |
+/** | |
+* dumps the entire structure nicely | |
+* @param string $string the explaining string | |
+*/ | |
+function dumpAllNicely($string = '') | |
+{ | |
+ global $tree; | |
+ | |
+ echo '<i><span style="color: #008000; text-decoration: underline;">' . $string . '</span></i><br>'; | |
+ $all = $tree->getBranch(); // get the entire structure sorted as the tree is, so we can simply foreach through it and show it | |
+ foreach ($all as $aElement) { | |
+ for ($i = 0; $i < $aElement['level']; ++$i) { | |
+ echo ' '; | |
+ } | |
+ echo '<span style="color: red">' . $aElement['name'] . '</span> ===> '; | |
+ $tree->varDump(array($aElement)); | |
+ } | |
+ echo '<br />'; | |
+ | |
+} | |
\ No newline at end of file | |
Property changes on: docs/funcs.php | |
___________________________________________________________________ | |
Added: svn:eol-style | |
## -0,0 +1 ## | |
+native | |
Added: svn:keywords | |
## -0,0 +1 ## | |
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL | |
Added: cvs2svn:cvs-rev | |
## -0,0 +1 ## | |
+1.1 | |
Index: docs/Memory_DBnested.php | |
=================================================================== | |
--- docs/Memory_DBnested.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/Memory_DBnested.php (.../trunk) (revision 321102) | |
@@ -1,58 +1,14 @@ | |
<?php | |
// $Id$ | |
-ini_set('error_reporting',E_ALL); | |
+include_once 'funcs.php'; | |
- /** | |
- * this is a helper function, so i dont have to write so many prints :-) | |
- * @param array $para the result returned by some method, that will be dumped | |
- * @param string $string the explaining string | |
- */ | |
- function dumpHelper($para, $string = '', $addArray = false) | |
- { | |
- global $tree, $element; | |
- if ($addArray) { | |
- eval( "\$res=array(".$para.');' ); | |
- } else { | |
- eval( "\$res=".$para.';' ); | |
- } | |
- echo '<b>'.$para.' </b><i><u><font color="#008000">'.$string.'</font></u></i><br />'; | |
- // this method dumps to the screen, since print_r or var_dump dont | |
- // work too good here, because the inner array is recursive | |
- // well, it looks ugly but one can see what is meant :-) | |
- $tree->varDump($res); | |
- echo '<br />'; | |
- | |
- } | |
- | |
- /** | |
- * dumps the entire structure nicely | |
- * @param string $string the explaining string | |
- */ | |
- function dumpAllNicely($string = '') | |
- { | |
- global $tree; | |
- | |
- echo '<i><u><font color="#008000">'.$string.'</font></u></i><br />'; | |
- $all = $tree->getNode(); // get the entire structure sorted as the tree is, so we can simply foreach through it and show it | |
- foreach($all as $aElement) { | |
- for ($i = 0; $i < $aElement['level']; $i++) { | |
- echo ' '; | |
- } | |
- echo '<font color="red">'.$aElement['name'].'</font> ===> '; | |
- $tree->varDump(array($aElement)); | |
- } | |
- echo '<br />'; | |
- | |
- } | |
- | |
- | |
/* | |
use this to build the db table | |
- CREATE TABLE Memory_Nested_DB ( | |
+ CREATE TABLE Memory_nestedTree ( | |
id int(11) NOT NULL default '0', | |
name varchar(255) NOT NULL default '', | |
l int(11) NOT NULL default '0', | |
@@ -62,7 +18,6 @@ | |
PRIMARY KEY (id) | |
); | |
- | |
This example demonstrates how to manage trees | |
that are saved in a DB, it uses a very simple | |
DB-structure, not nested trees (ok, that sucks, but it can be implemented :-) ) | |
@@ -78,10 +33,6 @@ | |
require_once 'Tree/Tree.php'; | |
// define the DB-table where the data shall be read from | |
- $options = array('table' => 'Memory_Nested_DB' | |
- ,'whereAddOn' => "comment=''" | |
- ); | |
- | |
// calling 'setupMemory' means to retreive a class, which works on trees, | |
// that are temporarily stored in the memory, in an array | |
// this means the entire tree is available at all time !!! | |
@@ -91,20 +42,34 @@ | |
// the class Memory/DBnested is only kind of a wrapper to read the entire tree | |
// and let u work on it, which to use should be chosen on case by case basis | |
+$config = array( | |
+ 'type' => 'Nested', | |
+ 'storage' => array( | |
+ 'name' => 'DB', | |
+ 'dsn' => 'mysql://root:hamstur@localhost/tree_test', | |
+ // 'connection' => | |
+ ), | |
+ 'options' => array( | |
+ 'table' => 'nestedTree', | |
+ 'order' => 'id', | |
+ 'fields' => array(), | |
+ 'whereAddOn' => "comment=''" | |
+ ), | |
+); | |
+ | |
+ | |
// using 'setupMemory' | |
- $tree = Tree::setupMemory('DBnested', | |
- 'mysql://root@localhost/tree_test', // the DSN | |
- $options); // pass the options we had assigned up there | |
+ $tree =& Tree::factoryMemory($config); | |
// add a new root element in the tree | |
- $rootId = $tree->add(array('name' => 'myElement')); | |
+ #$rootId = $tree->add(array('name' => 'myElement')); | |
// add an element under the new element we added | |
- $id = $tree->add(array('name' => 'subElement') , $rootId); | |
+ #$id = $tree->add(array('name' => 'subElement') , $rootId); | |
// add another element under the parent element we added | |
- $id = $tree->add(array('name' => 'anotherSubElement') , $rootId , $id); | |
- | |
+ #$id = $tree->add(array('name' => 'anotherSubElement') , $rootId , $id); | |
+$id = 0; | |
// call 'setup', to build the inner array, so we can work on the structure using the | |
// given methods | |
$tree->setup(); | |
@@ -119,7 +84,7 @@ | |
// you can also use: $tree->data[$id]['parent'] | |
$id = $tree->getIdByPath('myElement'); | |
- dumpHelper('$tree->getChild('.$id.')' , 'dump the child of "myElement"' , true); | |
+ dumpHelper('$tree->getChildren('.$id.', true)' , 'dump the child of "myElement"' , true); | |
// you can also use: $tree->data[$id]['child'] | |
$id = $tree->getIdByPath('myElement'); | |
@@ -127,11 +92,11 @@ | |
// you can also use: $tree->data[$id]['children'] | |
$id = $tree->getIdByPath('myElement/subElement'); | |
- dumpHelper('$tree->getNext('.$id.')' , 'dump the "next" of "myElement/subElement"' , true); | |
+ dumpHelper('$tree->nextSibling('.$id.')' , 'dump the "next" of "myElement/subElement"' , true); | |
// you can also use: $tree->data[$id]['next'] | |
$id = $tree->getIdByPath('myElement/anotherSubElement'); | |
- dumpHelper('$tree->getPrevious('.$id.')' , 'dump the "previous" of "myElement/anotherSubElement"' , true); | |
+ dumpHelper('$tree->previousSibling('.$id.')' , 'dump the "previous" of "myElement/anotherSubElement"' , true); | |
// you can also use: $tree->data[$id]['previous'] | |
$id = $tree->getIdByPath('myElement'); | |
@@ -141,18 +106,18 @@ | |
$id = $tree->getIdByPath('myElement'); | |
$element = $tree->data[$id]['child']['next']; // refer to the second child of 'myElement' | |
dumpHelper('$element[\'id\']' , 'demo2 of using the internal array, for referencing tree-nodes, see the code'); | |
-/* | |
+ | |
$id = $tree->getIdByPath('myElement/anotherSubElement'); | |
- $tree->move( $id , 0 ); | |
+ $tree->move($id , 0); | |
$tree->setup(); // rebuild the structure again, since we had changed it | |
dumpAllNicely( 'dump all, after "myElement/anotherSubElement" was moved under the root' ); | |
$moveId = $tree->getIdByPath('myElement'); | |
$id = $tree->getIdByPath('anotherSubElement'); | |
- $tree->move( $moveId , $id ); | |
+ $tree->move($moveId , $id); | |
$tree->setup(); // rebuild the structure again, since we had changed it | |
dumpAllNicely( 'dump all, after "myElement" was moved under the "anotherSubElement"' ); | |
-*/ | |
+ | |
$tree->setRemoveRecursively(true); | |
$tree->remove($rootId); | |
echo '<font color="red">ALL ELEMENTS HAVE BEEN REMOVED (uncomment this part to keep them in the DB after running this test script)</font>'; | |
Property changes on: docs/Memory_DBnested.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3 | |
+1.4 | |
Index: docs/TreeEditor/index.tpl | |
=================================================================== | |
Cannot display: file marked as a binary type. | |
svn:mime-type = application/vnd.groove-tool-template | |
Index: docs/TreeEditor/index.tpl | |
=================================================================== | |
--- docs/TreeEditor/index.tpl (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/TreeEditor/index.tpl (.../trunk) (revision 321102) | |
Property changes on: docs/TreeEditor/index.tpl | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.1 | |
+1.2 | |
Index: docs/TreeEditor/treeClass.php | |
=================================================================== | |
--- docs/TreeEditor/treeClass.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/TreeEditor/treeClass.php (.../trunk) (revision 321102) | |
@@ -1,18 +1,22 @@ | |
<?php | |
// | |
// $Log$ | |
+// Revision 1.1 2003/01/30 17:18:24 cain | |
+// - moved all examples to docs | |
+// - and make them work properly | |
+// | |
// Revision 1.1 2002/08/23 17:18:28 cain | |
// - a good example to show how the tree works | |
// | |
// | |
-require_once('Tree/Memory.php'); | |
+require_once 'Tree/Memory.php'; | |
class treeClass extends Tree_Memory | |
{ | |
- function getPathAsString( $id ) | |
+ function getPathAsString($id) | |
{ | |
return preg_replace('/Root\s-\s/','',parent::getPathAsString( $id , ' - ' )); | |
} | |
@@ -34,25 +38,22 @@ | |
* @return mixed an array if the node shall be visible | |
* nothing if the node shall not be shown | |
*/ | |
- function _walkForGettingVisibleFolders( $node ) | |
+ function _walkForGettingVisibleFolders($node) | |
{ | |
global $session; | |
- if( $node['id']==$this->getRootId() ) | |
+ if ($node['id'] == $this->getRootId()) { | |
return $node; | |
- | |
+ } | |
$parentsIds = $this->getParentsIds($node['id']); | |
- if( !@$this->_unfoldAll ) | |
- { | |
- foreach( $parentsIds as $aParentId ) | |
- { | |
- if( !@$session->temp->openProjectFolders[$aParentId] && | |
- $aParentId!=$node['id']) // dont check the node itself, since we only look if the parents are openend, then this $node is shown! | |
+ if (!@$this->_unfoldAll) { | |
+ foreach ($parentsIds as $aParentId) { | |
+ if (!@$session->temp->openProjectFolders[$aParentId] && | |
+ $aParentId != $node['id']) { // dont check the node itself, since we only look if the parents are openend, then this $node is shown! | |
return false; | |
+ } | |
} | |
- } | |
- else | |
- { | |
+ } else { | |
// if all folders shall be unfolded save the unfold-ids in the session | |
$session->temp->openProjectFolders[$node['id']] = $node['id']; | |
} | |
@@ -71,32 +72,24 @@ | |
function getAllVisible() | |
{ | |
$this->unfoldHandler(); | |
- return $this->walk( array(&$this,'_walkForGettingVisibleFolders') , 0 , 'ifArray' ); | |
+ return $this->walk(array(&$this, '_walkForGettingVisibleFolders'), 0, 'ifArray'); | |
} | |
function unfoldHandler() | |
{ | |
global $session; | |
- if( @$_REQUEST['unfoldAll'] ) | |
- { | |
+ if (@$_REQUEST['unfoldAll']) { | |
$this->_unfoldAll = true; | |
} | |
- if( @$_REQUEST['unfold'] ) | |
- { | |
- if( @$session->temp->openProjectFolders[$_REQUEST['unfold']] ) | |
- { | |
+ if (@$_REQUEST['unfold']) { | |
+ if (@$session->temp->openProjectFolders[$_REQUEST['unfold']]) { | |
unset($session->temp->openProjectFolders[$_REQUEST['unfold']]); | |
- } | |
- else | |
- { | |
+ } else { | |
$session->temp->openProjectFolders[$_REQUEST['unfold']] = $_REQUEST['unfold']; | |
} | |
} | |
} | |
- | |
- | |
} | |
- | |
?> | |
Property changes on: docs/TreeEditor/treeClass.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.1 | |
+1.2 | |
Index: docs/TreeEditor/index.php | |
=================================================================== | |
--- docs/TreeEditor/index.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/TreeEditor/index.php (.../trunk) (revision 321102) | |
@@ -1,105 +1,109 @@ | |
<?php | |
- // | |
- // $Id$ | |
- // | |
-//ini_set('include_path',realpath(dirname(__FILE__).'/../../../').':'.realpath(dirname(__FILE__).'/../../../../includes').':'.ini_get('include_path')); | |
-//ini_set('error_reporting',E_ALL); | |
+// $Id$ | |
+ini_set('error_reporting', E_ALL); | |
+ | |
################################################## | |
# | |
# init template engine | |
# | |
- // you need the template class from http://sf.net/projects/simpltpl | |
- if (!@include('HTML/Template/Xipe.php')) { | |
+ if (!@include 'HTML/Template/Xipe.php') { | |
print 'sorry, you need the template class PEAR::HTML_Template_Xipe<br>'. | |
'or if i have time i put the examples <a href="http://os.visionp.de/">here online</a>'; | |
die(); | |
} | |
- require_once('HTML/Template/Xipe/Filter/TagLib.php'); | |
- $options = array( 'templateDir' => dirname(__FILE__) ); | |
+ require_once 'HTML/Template/Xipe/Filter/TagLib.php'; | |
+ $options = array('templateDir' => dirname(__FILE__)); | |
$tpl = new HTML_Template_Xipe($options); | |
- require_once('HTML/Template/Xipe/Filter/Modifier.php'); | |
+ require_once 'HTML/Template/Xipe/Filter/Modifier.php'; | |
$modifiers = new HTML_Template_Xipe_Filter_Modifier($tpl->options); | |
- $tpl->registerPrefilter(array(&$modifiers,'imgSrc'), | |
- array(dirname(__FILE__),'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']))); | |
+ $tpl->registerPrefilter(array(&$modifiers, 'imgSrc'), | |
+ array(dirname(__FILE__), 'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']))); | |
// session stuff to save the opened folders etc. | |
session_start(); | |
- if(!session_is_registered('session')) | |
- { | |
+ if (empty($_SESSION['session'])) { | |
$session = new stdClass; // standard PHP-class constructor | |
- session_register('session'); | |
- $session->data = array(); | |
+ $_SESSION['session'] = $session; | |
$session->use = 'Filesystem'; | |
+ } else { | |
+ // since the class is read from the session it is not automatically made global | |
+ $session = $_SESSION['session']; | |
} | |
- else // since the class is read from the session it is not automatically made global | |
- { | |
- $session = &$_SESSION['session']; | |
- } | |
+ $session->data = array(); | |
+ | |
// set the source to use | |
- if( @$_REQUEST['use_DB'] ) | |
+ if (@$_REQUEST['use_DB']) { | |
$session->use = 'DB'; | |
- if( @$_REQUEST['use_Filesystem'] ) | |
+ } | |
+ if (@$_REQUEST['use_MDB']) { | |
+ $session->use = 'MDB'; | |
+ } | |
+ if (@$_REQUEST['use_Filesystem']) { | |
$session->use = 'Filesystem'; | |
- if( @$_REQUEST['use_XML'] ) | |
+ } | |
+ if (@$_REQUEST['use_XML']) { | |
$session->use = 'XML'; | |
- if( @$_REQUEST['use_Array'] ) | |
+ } | |
+ if (@$_REQUEST['use_Array']) { | |
$session->use = 'Array'; | |
+ } | |
+ if (!isset($session->use)) { | |
+ $session->use = 'DB'; | |
+ } | |
+ | |
################################################## | |
# | |
# actual tree stuff | |
# | |
- define('TABLE_TREE','Tree_Nested'); | |
- define('DB_DSN','mysql://root@localhost/test'); | |
+ define('TABLE_TREE', 'Tree_Nested'); | |
+ define('DB_DSN', 'mysql://root@localhost/tree_test'); | |
- require_once('treeClass.php'); | |
- if( $session->use == 'DB' ) | |
- { | |
- $options = array( 'table' => TABLE_TREE , 'order' => 'name'); | |
- $tree = new treeClass( 'DBnested' , DB_DSN , $options ); | |
- } | |
- if( $session->use == 'Filesystem' ) | |
- { | |
- # to let it work on the filesystem :-) | |
- $options = array( 'order' => 'name'); | |
- $tree = new treeClass( 'Filesystem' , dirname(__FILE__).'/tmp' , $options ); | |
- } | |
- if( $session->use == 'XML' ) | |
- { | |
- $tree = new treeClass( 'XML' , dirname(__FILE__).'/config.xml' ); | |
- } | |
- if( $session->use == 'Array' ) | |
- { | |
- // the actual data for the tree, they have to have the given structure | |
- $arrayData = array( 'name'=>'Root', | |
- 'children'=>array( | |
- array('name'=>'dir1'), | |
- array('name'=>'dir2', | |
- 'children'=>array( | |
- array('name'=>'dir2_1'), | |
- array('name'=>'dir2_2'), | |
- ) | |
- ), | |
- array('name'=>'dir3') | |
- ) | |
- ); | |
+ require_once 'treeClass.php'; | |
+ switch ($session->use) { | |
+ case 'MDB': | |
+ $options = array('table' => TABLE_TREE , 'order' => 'name'); | |
+ $tree = new treeClass('MDBnested', DB_DSN, $options); | |
+ break; | |
+ case 'Filesystem': | |
+ # to let it work on the filesystem :-) | |
+ $options = array('order' => 'name'); | |
+ $tree = new treeClass('Filesystem', '/tmp', $options); | |
+ case 'XML': | |
+ $tree = new treeClass('XML', dirname(__FILE__).'/config.xml'); | |
+ break; | |
+ case 'Array': | |
+ // the actual data for the tree, they have to have the given structure | |
+ $arrayData = array( 'name'=>'Root', | |
+ 'children'=>array( | |
+ array('name'=>'dir1'), | |
+ array('name'=>'dir2', | |
+ 'children'=>array( | |
+ array('name'=>'dir2_1'), | |
+ array('name'=>'dir2_2'), | |
+ ) | |
+ ), | |
+ array('name'=>'dir3') | |
+ ) | |
+ ); | |
- // any on an array | |
- $options = array( 'order' => 'name'); | |
- $tree = new treeClass( 'Array' , $arrayData , $options ); | |
+ // any on an array | |
+ $options = array('order' => 'name'); | |
+ $tree = new treeClass('Array', $arrayData, $options); | |
+ break; | |
+ case 'DB': | |
+ default: | |
+ $options = array('table' => TABLE_TREE , 'order' => 'name'); | |
+ $tree = new treeClass('DBnested', DB_DSN, $options); | |
+ break; | |
} | |
- | |
- | |
- | |
- | |
- if( PEAR::isError($res=$tree->setup()) ) | |
- { | |
+ if (PEAR::isError($res = $tree->setup())) { | |
$methodFailed = true; | |
$results[] = $res; | |
} | |
@@ -108,36 +112,33 @@ | |
// detect action | |
- if( @$_REQUEST['action_copy'] || @$_REQUEST['action_copy_x'] || | |
- @$_REQUEST['action_cut'] || @$_REQUEST['action_cut_x'] ) | |
+ if (@$_REQUEST['action_copy'] || @$_REQUEST['action_copy_x'] || | |
+ @$_REQUEST['action_cut'] || @$_REQUEST['action_cut_x']) | |
{ | |
- if( @$_REQUEST['action_copy'] || @$_REQUEST['action_copy_x']) $session->action = 'copy'; | |
- if( @$_REQUEST['action_cut'] || @$_REQUEST['action_cut_x'] ) $session->action = 'cut'; | |
+ if (@$_REQUEST['action_copy'] || @$_REQUEST['action_copy_x']) { | |
+ $session->action = 'copy'; | |
+ } | |
+ if (@$_REQUEST['action_cut'] || @$_REQUEST['action_cut_x'] ) { | |
+ $session->action = 'cut'; | |
+ } | |
- if( is_array($_REQUEST['selectedNodes']) && sizeof($_REQUEST['selectedNodes'])) | |
- { | |
+ if (is_array($_REQUEST['selectedNodes']) && | |
+ sizeof($_REQUEST['selectedNodes']) | |
+ ) { | |
$session->data = $_REQUEST['selectedNodes']; | |
- } | |
- else | |
- { | |
+ } else { | |
$session->action = ''; | |
} | |
} | |
- if( @$_REQUEST['action_paste'] || @$_REQUEST['action_paste_x'] ) | |
- { | |
- if( is_array($session->data) && sizeof($session->data)) | |
- { | |
- if( $session->action == 'copy' ) | |
- { | |
- if( is_array($_REQUEST['selectedNodes']) && sizeof($_REQUEST['selectedNodes'])) | |
- { | |
+ if (@$_REQUEST['action_paste'] || @$_REQUEST['action_paste_x']) { | |
+ if (is_array($session->data) && sizeof($session->data)) { | |
+ if ($session->action == 'copy') { | |
+ if (is_array($_REQUEST['selectedNodes']) && sizeof($_REQUEST['selectedNodes'])) { | |
$dest = $_REQUEST['selectedNodes']; | |
$sources = $session->data; | |
- foreach( $sources as $aSrc ) | |
- { | |
- foreach( $dest as $aDest ) | |
- { | |
+ foreach($sources as $aSrc) { | |
+ foreach($dest as $aDest) { | |
$methodCalls[] = "tree->copy( $aSrc , $aDest )"; | |
$results[] = $tree->copy( $aSrc , $aDest ); | |
} | |
@@ -147,25 +148,18 @@ | |
$session->data = array(); | |
unset($session->action); | |
$tree->setup(); | |
- } | |
- else | |
- { | |
+ } else { | |
$methodFailed = true; | |
$results = 'Please choose destination folder(s) to paste to!'; | |
} | |
} | |
- if( $session->action == 'cut') | |
- { | |
- if( !$_REQUEST['moveDest'] ) | |
- { | |
+ if ($session->action == 'cut') { | |
+ if (!$_REQUEST['moveDest']) { | |
$methodFailed = true; | |
$results = 'Please choose a destination to paste to!'; | |
- } | |
- else | |
- { | |
- foreach( $session->data as $aNodeId ) | |
- { | |
+ } else { | |
+ foreach($session->data as $aNodeId) { | |
$methodCalls[] = "tree->move( $aNodeId , {$_REQUEST['moveDest']} )"; | |
$results[] = $tree->move( $aNodeId , $_REQUEST['moveDest'] ); | |
} | |
@@ -177,24 +171,21 @@ | |
} | |
} | |
- if( (@$_REQUEST['action_delete'] || @$_REQUEST['action_delete_x']) && | |
- is_array($_REQUEST['selectedNodes']) && sizeof($_REQUEST['selectedNodes']) ) | |
+ if ((@$_REQUEST['action_delete'] || @$_REQUEST['action_delete_x']) && | |
+ is_array($_REQUEST['selectedNodes']) && sizeof($_REQUEST['selectedNodes'])) | |
{ | |
$rootId = $tree->getRootId(); | |
- foreach( $_REQUEST['selectedNodes'] as $aNodeId ) | |
- { | |
- if( $rootId == $aNodeId ) | |
- { | |
+ foreach($_REQUEST['selectedNodes'] as $aNodeId) { | |
+ if ($rootId == $aNodeId) { | |
$methodCalls[] = 0; | |
$results[] = 'Cant remove Root with this application!'; | |
$methodFailed = true; | |
- } | |
- else | |
- { | |
+ } else { | |
$methodCalls[] = "tree->remove( $aNodeId )"; | |
- $res = $tree->remove( $aNodeId ); | |
- if(PEAR::isError($res)) | |
+ $res = $tree->remove($aNodeId); | |
+ if (PEAR::isError($res)) { | |
$methodFailed = true; | |
+ } | |
$results[] = $res; | |
} | |
} | |
@@ -204,16 +195,16 @@ | |
} | |
- if( @$_REQUEST['action_add'] && | |
+ if (@$_REQUEST['action_add'] && | |
is_array($_REQUEST['selectedNodes']) && sizeof($_REQUEST['selectedNodes']) && | |
- $_REQUEST['newFolder'] ) | |
+ $_REQUEST['newFolder']) | |
{ | |
- foreach( $_REQUEST['selectedNodes'] as $aNodeId ) | |
- { | |
+ foreach($_REQUEST['selectedNodes'] as $aNodeId) { | |
$methodCalls[] = "tree->add( {$_REQUEST['newFolder']} , $aNodeId )"; | |
- $res = $tree->add( $_REQUEST['newFolder'] , $aNodeId ); | |
- if(PEAR::isError($res)) | |
+ $res = $tree->add($_REQUEST['newFolder'] , $aNodeId); | |
+ if (PEAR::isError($res)) { | |
$methodFailed = true; | |
+ } | |
$results[] = $res; | |
} | |
$session->data = array(); | |
@@ -224,13 +215,14 @@ | |
$allVisibleFolders = $tree->getAllVisible(); | |
- if( !@is_array($_REQUEST['selectedNodes']) ) | |
+ if (!@is_array($_REQUEST['selectedNodes'])) { | |
$_REQUEST['selectedNodes'] = array(); | |
+ } | |
################################################## | |
# | |
# show the template | |
# | |
$tpl->compile('index.tpl'); | |
- include($tpl->compiledTemplate); | |
+ include $tpl->compiledTemplate; | |
?> | |
Property changes on: docs/TreeEditor/index.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.2 | |
+1.3 | |
Index: docs/umbrello-uml.xmi | |
=================================================================== | |
--- docs/umbrello-uml.xmi (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/umbrello-uml.xmi (.../trunk) (revision 321102) | |
@@ -1,150 +1,236 @@ | |
<?xml version="1.0" encoding="UTF-8"?> | |
-<XMI xmlns:UML="org.omg/standards/UML" verified="false" timestamp="" xmi.version="1.2" > | |
+<XMI xmlns:UML="http://schema.omg.org/spec/UML/1.3" verified="false" timestamp="2006-04-21T06:27:41" xmi.version="1.2" > | |
<XMI.header> | |
<XMI.documentation> | |
<XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter> | |
- <XMI.exporterVersion>1.1</XMI.exporterVersion> | |
+ <XMI.exporterVersion>1.5.1</XMI.exporterVersion> | |
+ <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding> | |
</XMI.documentation> | |
- <XMI.model xmi.name="uml" href="/home/wk/public_html/timetool/includes_cvs/Tree/docs/uml.xmi" /> | |
<XMI.metamodel xmi.name="UML" href="UML.xml" xmi.version="1.3" /> | |
</XMI.header> | |
<XMI.content> | |
- <docsettings viewid="34" documentation="" uniqueid="48" /> | |
- <umlobjects> | |
- <UML:Class stereotype="" package="Tree" xmi.id="35" abstract="0" documentation="" name="Tree" static="0" scope="200" > | |
- <UML:Operation stereotype="" package="" xmi.id="36" type="void" abstract="0" documentation="" name="setup" static="0" scope="200" > | |
- <UML:Parameter stereotype="" package="" xmi.id="1" value="" type="string" abstract="0" documentation="" name="type" static="0" scope="200" /> | |
- <UML:Parameter stereotype="" package="" xmi.id="2" value="" type="string" abstract="0" documentation="" name="dsn" static="0" scope="200" /> | |
- <UML:Parameter stereotype="" package="" xmi.id="3" value="array()" type="int" abstract="0" documentation="" name="options" static="0" scope="200" /> | |
- </UML:Operation> | |
- </UML:Class> | |
- <UML:Class stereotype="" package="Tree" xmi.id="37" abstract="0" documentation="" name="Tree_Common" static="0" scope="200" > | |
- <UML:Attribute stereotype="" package="" xmi.id="38" value="array()" type="int" abstract="0" documentation="" name="options" static="0" scope="200" /> | |
- </UML:Class> | |
- <UML:Class stereotype="" package="Tree" xmi.id="40" abstract="0" documentation="" name="Tree_Memory" static="0" scope="200" /> | |
- <UML:Class stereotype="" package="Tree" xmi.id="41" abstract="0" documentation="" name="Tree_Dynamic_DBnested" static="0" scope="200" /> | |
- <UML:Class stereotype="" package="Tree" xmi.id="42" abstract="0" documentation="" name="Tree_Memory_DBnested" static="0" scope="200" /> | |
- <UML:Class stereotype="" package="Tree" xmi.id="43" abstract="0" documentation="" name="Tree_Memory_Array" static="0" scope="200" /> | |
- <UML:Class stereotype="" package="Tree" xmi.id="44" abstract="0" documentation="" name="Tree_Memory_DBsimple" static="0" scope="200" /> | |
- <UML:Class stereotype="" package="Tree" xmi.id="45" abstract="0" documentation="" name="Tree_Memory_Filesystem" static="0" scope="200" /> | |
- <UML:Class stereotype="" package="Tree" xmi.id="46" abstract="0" documentation="" name="Tree_Memory_XML" static="0" scope="200" /> | |
- <UML:Class stereotype="" package="Tree" xmi.id="47" abstract="0" documentation="" name="Tree_Options" static="0" scope="200" /> | |
- <UML:Class stereotype="" package="Tree" xmi.id="48" abstract="0" documentation="" name="Tree_OptionsDB" static="0" scope="200" /> | |
- </umlobjects> | |
+ <UML:Model isSpecification="false" isLeaf="false" isRoot="false" xmi.id="m1" isAbstract="false" name="UML Model" > | |
+ <UML:Namespace.ownedElement> | |
+ <UML:Package isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="50" isRoot="false" isAbstract="false" name="Tree" > | |
+ <UML:Namespace.ownedElement> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="35" isRoot="false" isAbstract="false" name="Tree" > | |
+ <UML:Classifier.feature> | |
+ <UML:Operation isSpecification="false" isLeaf="false" visibility="public" xmi.id="36" isRoot="false" isAbstract="false" isQuery="false" name="setup" > | |
+ <UML:BehavioralFeature.parameter> | |
+ <UML:Parameter kind="return" xmi.id="135" type="97" /> | |
+ <UML:Parameter isSpecification="false" visibility="public" xmi.id="1" value="" type="98" name="type" /> | |
+ <UML:Parameter isSpecification="false" visibility="public" xmi.id="2" value="" type="98" name="dsn" /> | |
+ <UML:Parameter isSpecification="false" visibility="public" xmi.id="3" value="array()" type="99" name="options" /> | |
+ </UML:BehavioralFeature.parameter> | |
+ </UML:Operation> | |
+ </UML:Classifier.feature> | |
+ </UML:Class> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="37" isRoot="false" isAbstract="false" name="Tree_Common" > | |
+ <UML:Classifier.feature> | |
+ <UML:Attribute isSpecification="false" visibility="public" xmi.id="38" initialValue="array()" type="99" name="options" /> | |
+ </UML:Classifier.feature> | |
+ </UML:Class> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="40" isRoot="false" isAbstract="false" name="Tree_Memory" > | |
+ <UML:GeneralizableElement.generalization> | |
+ <UML:Generalization xmi.idref="61" /> | |
+ <UML:Generalization xmi.idref="117" /> | |
+ </UML:GeneralizableElement.generalization> | |
+ </UML:Class> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="41" isRoot="false" isAbstract="false" name="Tree_Dynamic_SQLnested" > | |
+ <UML:GeneralizableElement.generalization> | |
+ <UML:Generalization xmi.idref="64" /> | |
+ <UML:Generalization xmi.idref="112" /> | |
+ </UML:GeneralizableElement.generalization> | |
+ </UML:Class> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="42" isRoot="false" isAbstract="false" name="Tree_Memory_SQLnested" > | |
+ <UML:GeneralizableElement.generalization> | |
+ <UML:Generalization xmi.idref="67" /> | |
+ </UML:GeneralizableElement.generalization> | |
+ </UML:Class> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="43" isRoot="false" isAbstract="false" name="Tree_Memory_Array" /> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="44" isRoot="false" isAbstract="false" name="Tree_Memory_SQLsimple" /> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="45" isRoot="false" isAbstract="false" name="Tree_Memory_Filesystem" /> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="46" isRoot="false" isAbstract="false" name="Tree_Memory_XML" /> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="47" isRoot="false" isAbstract="false" name="Tree_Options" > | |
+ <UML:GeneralizableElement.generalization> | |
+ <UML:Generalization xmi.idref="79" /> | |
+ </UML:GeneralizableElement.generalization> | |
+ </UML:Class> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="50" xmi.id="48" isRoot="false" isAbstract="false" name="Tree_OptionsDB" > | |
+ <UML:GeneralizableElement.generalization> | |
+ <UML:Generalization xmi.idref="76" /> | |
+ <UML:Generalization xmi.idref="107" /> | |
+ </UML:GeneralizableElement.generalization> | |
+ </UML:Class> | |
+ </UML:Namespace.ownedElement> | |
+ </UML:Package> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="97" isRoot="false" isAbstract="false" name="void" /> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="98" isRoot="false" isAbstract="false" name="string" /> | |
+ <UML:Class isSpecification="false" isLeaf="false" visibility="public" namespace="m1" xmi.id="99" isRoot="false" isAbstract="false" name="int" /> | |
+ <UML:Generalization isSpecification="false" child="40" visibility="public" namespace="m1" xmi.id="61" parent="37" discriminator="" name="" /> | |
+ <UML:Generalization isSpecification="false" child="41" visibility="public" namespace="m1" xmi.id="64" parent="37" discriminator="" name="" /> | |
+ <UML:Generalization isSpecification="false" child="42" visibility="public" namespace="m1" xmi.id="67" parent="41" discriminator="" name="" /> | |
+ <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="70" name="" > | |
+ <UML:Association.connection> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="71" aggregation="none" type="35" name="" /> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="72" aggregation="none" type="40" name="" /> | |
+ </UML:Association.connection> | |
+ </UML:Association> | |
+ <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="73" name="" > | |
+ <UML:Association.connection> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="false" xmi.id="74" aggregation="none" type="35" name="" /> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="75" aggregation="none" type="41" name="" /> | |
+ </UML:Association.connection> | |
+ </UML:Association> | |
+ <UML:Generalization isSpecification="false" child="48" visibility="public" namespace="m1" xmi.id="76" parent="37" discriminator="" name="" /> | |
+ <UML:Generalization isSpecification="false" child="47" visibility="public" namespace="m1" xmi.id="79" parent="48" discriminator="" name="" /> | |
+ <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="82" name="" > | |
+ <UML:Association.connection> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="83" aggregation="composite" type="40" name="" /> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="84" aggregation="none" type="42" name="" /> | |
+ </UML:Association.connection> | |
+ </UML:Association> | |
+ <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="85" name="" > | |
+ <UML:Association.connection> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="86" aggregation="composite" type="40" name="" /> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="87" aggregation="none" type="43" name="" /> | |
+ </UML:Association.connection> | |
+ </UML:Association> | |
+ <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="88" name="" > | |
+ <UML:Association.connection> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="89" aggregation="composite" type="40" name="" /> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="90" aggregation="none" type="44" name="" /> | |
+ </UML:Association.connection> | |
+ </UML:Association> | |
+ <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="91" name="" > | |
+ <UML:Association.connection> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="92" aggregation="composite" type="40" name="" /> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="93" aggregation="none" type="45" name="" /> | |
+ </UML:Association.connection> | |
+ </UML:Association> | |
+ <UML:Association isSpecification="false" visibility="public" namespace="m1" xmi.id="94" name="" > | |
+ <UML:Association.connection> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="95" aggregation="composite" type="40" name="" /> | |
+ <UML:AssociationEnd isSpecification="false" visibility="public" changeability="changeable" isNavigable="true" xmi.id="96" aggregation="none" type="46" name="" /> | |
+ </UML:Association.connection> | |
+ </UML:Association> | |
+ <UML:Generalization isSpecification="false" child="48" visibility="public" namespace="m1" xmi.id="107" parent="35" discriminator="" name="" /> | |
+ <UML:Generalization isSpecification="false" child="41" visibility="public" namespace="m1" xmi.id="112" parent="35" discriminator="" name="" /> | |
+ <UML:Generalization isSpecification="false" child="40" visibility="public" namespace="m1" xmi.id="117" parent="35" discriminator="" name="" /> | |
+ </UML:Namespace.ownedElement> | |
+ </UML:Model> | |
+ </XMI.content> | |
+ <XMI.extensions xmi.extender="umbrello" > | |
+ <docsettings viewid="34" documentation="" uniqueid="135" /> | |
<diagrams> | |
- <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" snapy="10" showatts="1" xmi.id="34" documentation="" type="402" showops="1" showpackage="1" name="class diagram" localid="30000" showstereotype="0" showscope="1" font="Clean,11,-1,5,50,0,0,0,1,0" linecolor="#ff0000" > | |
+ <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="1014" snapy="10" showatts="1" xmi.id="34" documentation="" type="402" showops="1" showpackage="1" name="class diagram" localid="30000" showstereotype="0" showscope="1" snapcsgrid="0" font="Clean,11,-1,5,50,0,0,0,1,0" linecolor="#ff0000" canvasheight="615" > | |
<widgets> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="443" showattsigs="601" usesdiagramusefillcolour="0" x="99" linecolour="#ff0000" y="66" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="45" usefillcolor="1" showattributes="1" xmi.id="35" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="172" showattsigs="601" usesdiagramusefillcolour="0" x="197" linecolour="#ff0000" y="180" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="45" usefillcolor="1" showattributes="1" xmi.id="37" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="146" showattsigs="601" usesdiagramusefillcolour="0" x="210" linecolour="#ff0000" y="371" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="36" usefillcolor="1" showattributes="1" xmi.id="40" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="227" showattsigs="601" usesdiagramusefillcolour="0" x="658" linecolour="#ff0000" y="184" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="36" usefillcolor="1" showattributes="1" xmi.id="41" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="222" showattsigs="601" usesdiagramusefillcolour="0" x="427" linecolour="#ff0000" y="307" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="36" usefillcolor="1" showattributes="1" xmi.id="42" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="190" showattsigs="601" usesdiagramusefillcolour="0" x="426" linecolour="#ff0000" y="357" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="36" usefillcolor="1" showattributes="1" xmi.id="43" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="220" showattsigs="601" usesdiagramusefillcolour="0" x="427" linecolour="#ff0000" y="411" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="36" usefillcolor="1" showattributes="1" xmi.id="44" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="226" showattsigs="601" usesdiagramusefillcolour="0" x="427" linecolour="#ff0000" y="464" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="36" usefillcolor="1" showattributes="1" xmi.id="45" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="184" showattsigs="601" usesdiagramusefillcolour="0" x="427" linecolour="#ff0000" y="517" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="36" usefillcolor="1" showattributes="1" xmi.id="46" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="147" showattsigs="601" usesdiagramusefillcolour="0" x="24" linecolour="#ff0000" y="320" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="36" usefillcolor="1" showattributes="1" xmi.id="47" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
- <UML:ConceptWidget usesdiagramfillcolour="0" width="168" showattsigs="601" usesdiagramusefillcolour="0" x="13" linecolour="#ff0000" y="252" showopsigs="601" usesdiagramlinecolour="0" fillcolour="#ffffc0" height="36" usefillcolor="1" showattributes="1" xmi.id="48" showoperations="1" showpackage="1" showscope="1" showstereotype="0" font="Clean,11,-1,5,50,0,0,0,1,0" /> | |
+ <classwidget usesdiagramfillcolour="0" width="550" showattsigs="601" usesdiagramusefillcolour="0" x="99" y="66" showopsigs="601" linewidth="none" fillcolour="#ffffc0" height="50" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="35" showoperations="1" showpackage="1" showscope="1" font="Clean,11,-1,5,75,0,0,0,1,0" linecolor="#ff0000" /> | |
+ <classwidget usesdiagramfillcolour="0" width="165" showattsigs="601" usesdiagramusefillcolour="0" x="84" y="246" showopsigs="601" linewidth="none" fillcolour="#ffffc0" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="40" showoperations="1" showpackage="1" showscope="1" font="Clean,11,-1,5,75,0,0,0,1,0" linecolor="#ff0000" /> | |
+ <classwidget usesdiagramfillcolour="0" width="264" showattsigs="601" usesdiagramusefillcolour="0" x="658" y="184" showopsigs="601" linewidth="none" fillcolour="#ffffc0" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="41" showoperations="1" showpackage="1" showscope="1" font="Clean,11,-1,5,75,0,0,0,1,0" linecolor="#ff0000" /> | |
+ <classwidget usesdiagramfillcolour="0" width="255" showattsigs="601" usesdiagramusefillcolour="0" x="488" y="331" showopsigs="601" linewidth="none" fillcolour="#ffffc0" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="42" showoperations="1" showpackage="1" showscope="1" font="Clean,11,-1,5,75,0,0,0,1,0" linecolor="#ff0000" /> | |
+ <classwidget usesdiagramfillcolour="0" width="219" showattsigs="601" usesdiagramusefillcolour="0" x="209" y="348" showopsigs="601" linewidth="none" fillcolour="#ffffc0" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="43" showoperations="1" showpackage="1" showscope="1" font="Clean,11,-1,5,75,0,0,0,1,0" linecolor="#ff0000" /> | |
+ <classwidget usesdiagramfillcolour="0" width="255" showattsigs="601" usesdiagramusefillcolour="0" x="154" y="399" showopsigs="601" linewidth="none" fillcolour="#ffffc0" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="44" showoperations="1" showpackage="1" showscope="1" font="Clean,11,-1,5,75,0,0,0,1,0" linecolor="#ff0000" /> | |
+ <classwidget usesdiagramfillcolour="0" width="264" showattsigs="601" usesdiagramusefillcolour="0" x="54" y="449" showopsigs="601" linewidth="none" fillcolour="#ffffc0" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="45" showoperations="1" showpackage="1" showscope="1" font="Clean,11,-1,5,75,0,0,0,1,0" linecolor="#ff0000" /> | |
+ <classwidget usesdiagramfillcolour="0" width="201" showattsigs="601" usesdiagramusefillcolour="0" x="42" y="512" showopsigs="601" linewidth="none" fillcolour="#ffffc0" height="40" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="46" showoperations="1" showpackage="1" showscope="1" font="Clean,11,-1,5,75,0,0,0,1,0" linecolor="#ff0000" /> | |
</widgets> | |
<messages/> | |
<associations> | |
- <UML:AssocWidget totalcounta="4" indexa="2" totalcountb="2" indexb="1" widgetbid="37" widgetaid="40" documentation="" type="500" > | |
+ <assocwidget totalcounta="3" indexa="2" totalcountb="2" indexb="1" linewidth="none" widgetbid="41" widgetaid="42" xmi.id="67" linecolor="none" > | |
<linepath> | |
- <startpoint startx="283" starty="371" /> | |
- <endpoint endx="283" endy="225" /> | |
+ <startpoint startx="658" starty="331" /> | |
+ <endpoint endx="790" endy="224" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="37" widgetaid="41" documentation="" type="500" > | |
+ </assocwidget> | |
+ <assocwidget totalcounta="5" indexa="1" totalcountb="3" indexb="1" linewidth="none" widgetbid="40" widgetaid="35" xmi.id="70" linecolor="none" > | |
<linepath> | |
- <startpoint startx="658" starty="202" /> | |
- <endpoint endx="369" endy="202" /> | |
+ <startpoint startx="209" starty="116" /> | |
+ <endpoint endx="139" endy="246" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="41" widgetaid="42" documentation="" type="500" > | |
+ </assocwidget> | |
+ <assocwidget totalcounta="5" indexa="3" totalcountb="3" indexb="1" linewidth="none" widgetbid="41" widgetaid="35" xmi.id="73" linecolor="none" > | |
<linepath> | |
- <startpoint startx="538" starty="307" /> | |
- <endpoint endx="771" endy="220" /> | |
+ <startpoint startx="429" starty="116" /> | |
+ <endpoint endx="746" endy="184" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="3" indexa="1" totalcountb="4" indexb="1" widgetbid="40" widgetaid="35" documentation="" type="512" > | |
+ </assocwidget> | |
+ <assocwidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" linewidth="none" widgetbid="42" widgetaid="40" xmi.id="82" linecolor="none" > | |
<linepath> | |
- <startpoint startx="246" starty="111" /> | |
- <endpoint endx="246" endy="371" /> | |
+ <startpoint startx="249" starty="266" /> | |
+ <endpoint endx="573" endy="331" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="3" indexa="2" totalcountb="2" indexb="1" widgetbid="41" widgetaid="35" documentation="" type="512" > | |
+ </assocwidget> | |
+ <assocwidget totalcounta="5" indexa="4" totalcountb="2" indexb="1" linewidth="none" widgetbid="43" widgetaid="40" xmi.id="85" linecolor="none" > | |
<linepath> | |
- <startpoint startx="394" starty="111" /> | |
- <endpoint endx="771" endy="184" /> | |
+ <startpoint startx="216" starty="286" /> | |
+ <endpoint endx="318" endy="348" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="37" widgetaid="48" documentation="" type="500" > | |
+ </assocwidget> | |
+ <assocwidget totalcounta="5" indexa="3" totalcountb="2" indexb="1" linewidth="none" widgetbid="44" widgetaid="40" xmi.id="88" linecolor="none" > | |
<linepath> | |
- <startpoint startx="97" starty="252" /> | |
- <endpoint endx="197" endy="202" /> | |
+ <startpoint startx="183" starty="286" /> | |
+ <endpoint endx="281" endy="399" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="2" indexb="1" widgetbid="48" widgetaid="47" documentation="" type="500" > | |
+ </assocwidget> | |
+ <assocwidget totalcounta="5" indexa="2" totalcountb="2" indexb="1" linewidth="none" widgetbid="45" widgetaid="40" xmi.id="91" linecolor="none" > | |
<linepath> | |
- <startpoint startx="97" starty="320" /> | |
- <endpoint endx="97" endy="288" /> | |
+ <startpoint startx="150" starty="286" /> | |
+ <endpoint endx="186" endy="449" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="4" indexb="3" widgetbid="40" widgetaid="42" documentation="" type="510" > | |
+ </assocwidget> | |
+ <assocwidget totalcounta="5" indexa="1" totalcountb="2" indexb="1" linewidth="none" widgetbid="46" widgetaid="40" xmi.id="94" linecolor="none" > | |
<linepath> | |
- <startpoint startx="427" starty="325" /> | |
- <endpoint endx="319" endy="371" /> | |
+ <startpoint startx="117" starty="286" /> | |
+ <endpoint endx="142" endy="512" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="40" widgetaid="43" documentation="" type="510" > | |
+ </assocwidget> | |
+ <assocwidget totalcounta="3" indexa="2" totalcountb="5" indexb="4" linewidth="none" widgetbid="35" widgetaid="41" xmi.id="112" linecolor="none" > | |
<linepath> | |
- <startpoint startx="426" starty="375" /> | |
- <endpoint endx="356" endy="383" /> | |
+ <startpoint startx="834" starty="184" /> | |
+ <endpoint endx="539" endy="116" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="40" widgetaid="44" documentation="" type="510" > | |
+ </assocwidget> | |
+ <assocwidget totalcounta="3" indexa="2" totalcountb="5" indexb="2" linewidth="none" widgetbid="35" widgetaid="40" xmi.id="117" linecolor="none" > | |
<linepath> | |
- <startpoint startx="537" starty="411" /> | |
- <endpoint endx="356" endy="395" /> | |
+ <startpoint startx="194" starty="246" /> | |
+ <endpoint endx="319" endy="116" /> | |
</linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="1" widgetbid="40" widgetaid="45" documentation="" type="510" > | |
- <linepath> | |
- <startpoint startx="540" starty="464" /> | |
- <endpoint endx="258" endy="407" /> | |
- </linepath> | |
- </UML:AssocWidget> | |
- <UML:AssocWidget totalcounta="2" indexa="1" totalcountb="3" indexb="2" widgetbid="40" widgetaid="46" documentation="" type="510" > | |
- <linepath> | |
- <startpoint startx="519" starty="517" /> | |
- <endpoint endx="307" endy="407" /> | |
- </linepath> | |
- </UML:AssocWidget> | |
+ </assocwidget> | |
</associations> | |
</diagram> | |
</diagrams> | |
<listview> | |
- <listitem open="1" type="800" id="-1" label="Views" > | |
- <listitem open="1" type="801" id="-1" label="Logical View" > | |
- <listitem open="1" type="813" id="35" label="Tree" > | |
- <listitem open="0" type="815" id="36" label="setup" /> | |
+ <listitem open="1" type="800" label="Views" > | |
+ <listitem open="1" type="801" label="Logical View" > | |
+ <listitem open="1" type="813" id="35" > | |
+ <listitem open="0" type="815" id="36" /> | |
</listitem> | |
- <listitem open="1" type="813" id="37" label="Tree_Common" > | |
- <listitem open="0" type="814" id="38" label="options" /> | |
+ <listitem open="1" type="813" id="37" > | |
+ <listitem open="0" type="814" id="38" /> | |
</listitem> | |
- <listitem open="1" type="813" id="41" label="Tree_Dynamic_DBnested" /> | |
- <listitem open="1" type="813" id="40" label="Tree_Memory" /> | |
- <listitem open="1" type="813" id="43" label="Tree_Memory_Array" /> | |
- <listitem open="1" type="813" id="42" label="Tree_Memory_DBnested" /> | |
- <listitem open="1" type="813" id="44" label="Tree_Memory_DBsimple" /> | |
- <listitem open="1" type="813" id="45" label="Tree_Memory_Filesystem" /> | |
- <listitem open="1" type="813" id="46" label="Tree_Memory_XML" /> | |
- <listitem open="1" type="813" id="47" label="Tree_Options" /> | |
- <listitem open="1" type="813" id="48" label="Tree_OptionsDB" /> | |
- <listitem open="0" type="807" id="34" label="class diagram" /> | |
+ <listitem open="1" type="813" id="41" /> | |
+ <listitem open="1" type="813" id="40" /> | |
+ <listitem open="1" type="813" id="43" /> | |
+ <listitem open="1" type="813" id="42" /> | |
+ <listitem open="1" type="813" id="44" /> | |
+ <listitem open="1" type="813" id="45" /> | |
+ <listitem open="1" type="813" id="46" /> | |
+ <listitem open="1" type="813" id="47" /> | |
+ <listitem open="1" type="813" id="48" /> | |
+ <listitem open="0" type="813" id="99" /> | |
+ <listitem open="0" type="813" id="98" /> | |
+ <listitem open="0" type="813" id="97" /> | |
+ <listitem open="0" type="818" id="50" /> | |
+ <listitem open="0" type="830" label="Datatypes" /> | |
</listitem> | |
- <listitem open="1" type="802" id="-1" label="Use Case View" /> | |
+ <listitem open="1" type="802" label="Use Case View" /> | |
+ <listitem open="1" type="821" label="Component View" /> | |
+ <listitem open="1" type="827" label="Deployment View" /> | |
+ <listitem open="1" type="836" label="Entity Relationship Model" /> | |
</listitem> | |
</listview> | |
- </XMI.content> | |
+ <codegeneration> | |
+ <codegenerator language="SQL" /> | |
+ </codegeneration> | |
+ </XMI.extensions> | |
</XMI> | |
Property changes on: docs/umbrello-uml.xmi | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.1 | |
+1.2 | |
Index: docs/Memory_DBsimple.php | |
=================================================================== | |
--- docs/Memory_DBsimple.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/Memory_DBsimple.php (.../trunk) (revision 321102) | |
@@ -1,63 +1,16 @@ | |
<?php | |
- // | |
- // $Id$ | |
- // | |
+// $Id$ | |
-//ini_set('include_path',realpath(dirname(__FILE__).'/../../').':'.realpath(dirname(__FILE__).'/../../../includes').':'.ini_get('include_path')); | |
-//ini_set('error_reporting',E_ALL); | |
+include_once 'funcs.php'; | |
- /** | |
- * this is a helper function, so i dont have to write so many prints :-) | |
- * @param array $para the result returned by some method, that will be dumped | |
- * @param string $string the explaining string | |
- */ | |
- function dumpHelper($para, $string = '', $addArray = false) | |
- { | |
- global $tree,$element; | |
- if ($addArray) { | |
- eval("\$res=array(".$para.');'); | |
- } else { | |
- eval("\$res=".$para.';'); | |
- } | |
- echo '<b>' . $para . ' </b><i><u><font color="#008000">' . $string . '</font></u></i><br>'; | |
- // this method dumps to the screen, since print_r or var_dump dont | |
- // work too good here, because the inner array is recursive | |
- // well, it looks ugly but one can see what is meant :-) | |
- $tree->varDump($res); | |
- echo '<br>'; | |
- | |
- } | |
- | |
- /** | |
- * dumps the entire structure nicely | |
- * @param string $string the explaining string | |
- */ | |
- function dumpAllNicely($string = '') | |
- { | |
- global $tree; | |
- | |
- echo '<i><u><font color="#008000">' . $string . '</font></u></i><br>'; | |
- $all = $tree->getNode(); // get the entire structure sorted as the tree is, so we can simply foreach through it and show it | |
- foreach($all as $aElement) { | |
- for ($i = 0; $i < $aElement['level']; $i++) { | |
- echo ' '; | |
- } | |
- echo $aElement['name'].' ===> '; | |
- $tree->varDump(array($aElement)); | |
- } | |
- echo '<br>'; | |
- | |
- } | |
- | |
- | |
/* | |
use this to build the db table | |
CREATE TABLE test_tree ( | |
id int(11) NOT NULL auto_increment, | |
- parentId int(11) NOT NULL default '0', | |
+ parent int(11) NOT NULL default '0', | |
name varchar(255) NOT NULL default '', | |
PRIMARY KEY (id) | |
) | |
@@ -78,30 +31,39 @@ | |
require_once 'Tree/Tree.php'; | |
// define the DB-table where the data shall be read from | |
- $options = array('table' => 'test_tree', | |
- 'order' => 'id' // when reading the data from the db sort them by id, this is only for ensuring | |
- // for 'getNext' of "myElement/subElement" in this example to find "myElement/anotherSubElement" | |
- // you can simply sort it by "name" and it would be in alphabetical order | |
- ); | |
- | |
+ // when reading the data from the db sort them by id, this is only for ensuring | |
+ // for 'getNext' of "myElement/subElement" in this example to find "myElement/anotherSubElement" | |
+ // you can simply sort it by "name" and it would be in alphabetical order | |
// calling 'setupMemory' means to retreive a class, which works on trees, | |
// that are temporarily stored in the memory, in an array | |
// this means the entire tree is available at all time | |
// consider the resource usage and it's not to suggested to work | |
// on huge trees (upto 1000 elements it should be ok, depending on your environment and requirements) | |
// using 'setupMemory' | |
- $tree = Tree::setupMemory('DBsimple', // use the simple DB schema | |
- 'mysql://root@localhost/tree_test', // the DSN | |
- $options); // pass the options we had assigned up there | |
+ $config = array( | |
+ 'type' => 'Simple', | |
+ 'storage' => array( | |
+ 'name' => 'DB', | |
+ 'dsn' => 'mysql://root:hamstur@localhost/tree_test', | |
+ // 'connection' => $db, | |
+ ), | |
+ 'options' => array( | |
+ 'table' => 'test_tree', | |
+ 'order' => 'id', | |
+ 'fields' => array(), | |
+ ), | |
+ ); | |
+ $tree =& Tree::factoryMemory($config); | |
+ | |
// add a new root element in the tree | |
$parentId = $tree->add(array('name' => 'myElement')); | |
// add an element under the new element we added | |
- $id = $tree->add(array('name' => 'subElement') , $parentId ); | |
+ $id = $tree->add(array('name' => 'subElement'), $parentId); | |
// add another element under the parent element we added | |
- $id = $tree->add(array('name' => 'anotherSubElement') , $parentId ); | |
+ $id = $tree->add(array('name' => 'anotherSubElement'), $parentId); | |
// call 'setup', to build the inner array, so we can work on the structure using the | |
// given methods | |
@@ -117,7 +79,7 @@ | |
// you can also use: $tree->data[$id]['parent'] | |
$id = $tree->getIdByPath('myElement'); | |
- dumpHelper('$tree->getChild('.$id.')' , 'dump the child of "myElement"' , true); | |
+ dumpHelper('$tree->getChildren('.$id.', true)' , 'dump the child of "myElement"' , true); | |
// you can also use: $tree->data[$id]['child'] | |
$id = $tree->getIdByPath('myElement'); | |
@@ -125,21 +87,13 @@ | |
// you can also use: $tree->data[$id]['children'] | |
$id = $tree->getIdByPath('myElement/subElement'); | |
- dumpHelper('$tree->getNext('.$id.')' , 'dump the "next" of "myElement/subElement"' , true); | |
+ dumpHelper('$tree->nextSibling('.$id.')' , 'dump the "next" of "myElement/subElement"' , true); | |
// you can also use: $tree->data[$id]['next'] | |
$id = $tree->getIdByPath('myElement/anotherSubElement'); | |
- dumpHelper('$tree->getPrevious('.$id.')' , 'dump the "previous" of "myElement/anotherSubElement"' , true); | |
+ dumpHelper('$tree->prevSibling('.$id.')' , 'dump the "previous" of "myElement/anotherSubElement"' , true); | |
// you can also use: $tree->data[$id]['previous'] | |
- $id = $tree->getIdByPath('myElement'); | |
- $element = $tree->data[$id]['child']['next']['parent']; // refer to yourself again, in a very complicated way :-) | |
- dumpHelper('$element[\'id\']' , 'demo of using the internal array, for referencing tree-nodes, see the code'); | |
- | |
- $id = $tree->getIdByPath('myElement'); | |
- $element = $tree->data[$id]['child']['next']; // refer to the second child of 'myElement' | |
- dumpHelper('$element[\'id\']' , 'demo2 of using the internal array, for referencing tree-nodes, see the code'); | |
- | |
$id = $tree->getIdByPath('myElement/anotherSubElement'); | |
$tree->move($id , 0); | |
$tree->setup(); // rebuild the structure again, since we had changed it | |
@@ -147,12 +101,12 @@ | |
$moveId = $tree->getIdByPath('myElement'); | |
$id = $tree->getIdByPath('anotherSubElement'); | |
- $tree->move( $moveId , $id ); | |
- $tree->setup(); // rebuild the structure again, since we had changed it | |
+ #$tree->move( $moveId , $id ); | |
+ #$tree->setup(); // rebuild the structure again, since we had changed it | |
dumpAllNicely('dump all, after "myElement" was moved under the "anotherSubElement"'); | |
- $tree->setRemoveRecursively(true); | |
- $tree->remove(0); | |
- echo '<font color="red">ALL ELEMENTS HAVE BEEN REMOVED (uncomment this part to keep them in the DB after running this test script)</font>'; | |
+ #$tree->setRemoveRecursively(true); | |
+ #$tree->remove(0); | |
+ #echo '<font color="red">ALL ELEMENTS HAVE BEEN REMOVED (uncomment this part to keep them in the DB after running this test script)</font>'; | |
?> | |
Property changes on: docs/Memory_DBsimple.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3 | |
+1.4 | |
Index: docs/Memory_XML.php | |
=================================================================== | |
--- docs/Memory_XML.php (.../branches/Tree_0_3_0) (revision 321102) | |
+++ docs/Memory_XML.php (.../trunk) (revision 321102) | |
@@ -1,10 +1,7 @@ | |
<?php | |
- // | |
- // $Id$ | |
- // | |
+// $Id$ | |
-//ini_set('include_path',realpath(dirname(__FILE__).'/../../').':'.realpath(dirname(__FILE__).'/../../../includes').':'.ini_get('include_path')); | |
-//ini_set('error_reporting',E_ALL); | |
+ini_set('error_reporting', E_ALL); | |
/** | |
* this is a helper function, so i dont have to write so many prints :-) | |
* @param array $para the result returned by some method, that will be dumped | |
@@ -14,12 +11,12 @@ | |
{ | |
global $tree; | |
- echo'<i><u><font color="#008000">' . $string . '</font></u></i><br>'; | |
+ echo'<i><u><span style="color: #008000;">' . $string . '</span></u></i><br />'; | |
// this method dumps to the screen, since print_r or var_dump dont | |
// work too good here, because the inner array is recursive | |
// well, it looks ugly but one can see what is meant :-) | |
$tree->varDump($para); | |
- echo '<br>'; | |
+ echo '<br />'; | |
} | |
@@ -31,7 +28,7 @@ | |
{ | |
global $tree; | |
- echo '<i><u><font color="#008000">' . $string . '</font></u></i><br>'; | |
+ echo '<i><u><span style="color: #008000;">' . $string . '</span></u></i><br />'; | |
$all = $tree->getNode(); // get the entire structure sorted as the tree is, so we can simply foreach through it and show it | |
foreach ($all as $aElement) { | |
for ($i = 0; $i < $aElement['level']; $i++) { | |
@@ -45,10 +42,10 @@ | |
echo 'attributes - '; | |
print_r($aElement['attributes']); | |
- echo '<br>'; | |
+ echo '<br />'; | |
} | |
- echo '<br>'; | |
+ echo '<br />'; | |
} | |
@@ -80,10 +77,18 @@ | |
// consider the resource usage and it's not to suggested to work | |
// on huge trees (upto 1000 elements it should be ok, depending on your environment and requirements) | |
// using 'setupMemory' | |
- $tree = Tree::setupMemory('XML', // use the XML class to read an xml file | |
- 'config.xml' // the DSN | |
- ); | |
+ $config = array( | |
+ 'type' => '', | |
+ 'storage' => array( | |
+ 'name' => 'XML', | |
+ 'dsn' => 'config.xml', | |
+ ), | |
+ 'options' => array( | |
+ ), | |
+ ); | |
+ $tree =& Tree::factoryMemory($config); | |
+ | |
// methods 'add' 'remove' and so on are not implemented yet, you can only read the tree for now | |
// and navigate inside of it | |
@@ -95,10 +100,10 @@ | |
// get the path of the last inserted element | |
echo 'id='.$id = $tree->getIdByPath('simpletemplate/options/delimiter'); | |
- dumpHelper( $tree->getPath( $id ) , 'dump the path from "simpletemplate/options/delimiter"'); | |
+ dumpHelper( $tree->getPath($id), 'dump the path from "simpletemplate/options/delimiter"'); | |
$id = $tree->getIdByPath('simpletemplate/options'); | |
- dumpHelper(array($tree->getParent($id)) , 'dump the parent of "simpletemplate/options"'); | |
+ dumpHelper(array($tree->getParent($id)), 'dump the parent of "simpletemplate/options"'); | |
// you can also use: $tree->data[$id]['parent'] | |
$id = $tree->getIdByPath('simpletemplate'); | |
@@ -106,15 +111,15 @@ | |
// you can also use: $tree->data[$id]['child'] | |
$id = $tree->getIdByPath('simpletemplate/prefilter'); | |
- dumpHelper($tree->getChildren($id) , 'dump the children of "simpletemplate/prefilter"'); | |
+ dumpHelper($tree->getChildren($id), 'dump the children of "simpletemplate/prefilter"'); | |
// you can also use: $tree->data[$id]['children'] | |
$id = $tree->getIdByPath('simpletemplate/options'); | |
- dumpHelper(array($tree->getNext($id)) , 'dump the "next" of "simpletemplate/options"'); | |
+ dumpHelper(array($tree->getNext($id)), 'dump the "next" of "simpletemplate/options"'); | |
// you can also use: $tree->data[$id]['next'] | |
$id = $tree->getIdByPath('simpletemplate/prefilter'); | |
- dumpHelper( array($tree->getPrevious($id)) , 'dump the "previous" of "simpletemplate/prefilter"'); | |
+ dumpHelper(array($tree->getPrevious($id)), 'dump the "previous" of "simpletemplate/prefilter"'); | |
// you can also use: $tree->data[$id]['previous'] | |
@@ -123,18 +128,18 @@ | |
dumpHelper($element['id'] , 'demo of using the internal array, for referencing tree-nodes'); | |
/* | |
-NOT IMPLEMENTED YET | |
+ NOT IMPLEMENTED YET | |
$id = $tree->getIdByPath('myElement/anotherSubElement'); | |
- $tree->move( $id , 0 ); | |
+ $tree->move($id, 0); | |
$tree->setup(); // rebuild the structure again, since we had changed it | |
- dumpAllNicely( 'dump all, after "myElement/anotherSubElement" was moved under the root' ); | |
+ dumpAllNicely('dump all, after "myElement/anotherSubElement" was moved under the root'); | |
$moveId = $tree->getIdByPath('myElement'); | |
$id = $tree->getIdByPath('anotherSubElement'); | |
- $tree->move( $moveId , $id ); | |
+ $tree->move($moveId, $id); | |
$tree->setup(); // rebuild the structure again, since we had changed it | |
- dumpAllNicely( 'dump all, after "myElement" was moved under the "anotherSubElement"' ); | |
+ dumpAllNicely('dump all, after "myElement" was moved under the "anotherSubElement"'); | |
$tree->setRemoveRecursively(true); | |
Property changes on: docs/Memory_XML.php | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.3 | |
+1.4 | |
Index: package.xml | |
=================================================================== | |
--- package.xml (.../branches/Tree_0_3_0) (revision 321102) | |
+++ package.xml (.../trunk) (revision 321102) | |
@@ -5,38 +5,26 @@ | |
http://pear.php.net/dtd/package-2.0.xsd"> | |
<name>Tree</name> | |
<channel>pear.php.net</channel> | |
- <summary>Generic tree management, currently supports databases (via DB, MDB and MDB2) and XML as data sources</summary> | |
- <description>Provides methods to read and manipulate trees, which are stored in a database (via DB, MDB and MDB2) or an XML file. | |
- | |
-The trees can be stored in the DB either as nested trees. | |
-Or as simple trees, which use parentId-like structure. | |
+ <summary>Generic tree management, currently supports DB, MDB and XML as data sources</summary> | |
+ <description>Provides methods to read and manipulate trees, which are stored in the DB/MDB | |
+or an XML file. The trees can be stored in the DB either as nested trees. | |
+Or as simple trees ('brain dead method'), which use parentId-like structure. | |
Currently XML data can only be read from a file and accessed. | |
The package offers a big number of methods to access and manipulate trees. | |
For example methods like: getRoot, getChild[ren[Ids]], getParent[s[Ids]], getPath[ById] and many | |
more. | |
- | |
There are two ways of retreiving the data from the place where they are stored, | |
one is by reading the entire tree into the memory - the Memory way. The other | |
is reading the tree nodes as needed (very useful in combination with huge trees | |
and the nested set model). | |
- | |
The package is designed that way that it is possible to convert/copy tree data | |
-from either structure to another (from XML into DB). | |
- | |
- | |
-This package has the following drivers: | |
-* DB | |
-* MDB | |
-* MDB2 | |
-* Array | |
-* XML | |
-* FileSystem | |
+from either structure to another (from XML into DB/MDB). | |
</description> | |
<lead> | |
<name>Wolfram Kriesing</name> | |
<user>cain</user> | |
<email>[email protected]</email> | |
- <active>no</active> | |
+ <active>yes</active> | |
</lead> | |
<lead> | |
<name>Helgi Þormar</name> | |
@@ -44,52 +32,65 @@ | |
<email>[email protected]</email> | |
<active>yes</active> | |
</lead> | |
- <lead> | |
- <name>Daniel Convissor</name> | |
- <user>danielc</user> | |
- <email>[email protected]</email> | |
- <active>no</active> | |
- </lead> | |
- <date>2011-12-09</date> | |
+ <date>2007-06-02</date> | |
+ <time>00:25:37</time> | |
<version> | |
- <release>0.3.5</release> | |
- <api>0.3.5</api> | |
+ <release>0.4.0</release> | |
+ <api>0.4.0</api> | |
</version> | |
<stability> | |
<release>beta</release> | |
<api>beta</api> | |
</stability> | |
<license uri="http://www.php.net/license">PHP License</license> | |
- <notes> | |
-* Fixed Bug 19119 Only variable references should be returned by reference. | |
+ <notes>This is a rewrite of Tree so there are BC breaks! Please look at the examples to see how things are done now. | |
+* add unit test, at least for all new/modified methods | |
+* setup* in Tree.php renamed to factory* | |
+* Configurations rewritten, look at examples to see how it's done now. | |
+* From now on changing anything in regards to fields can not be done via setOption. | |
+* Removed these functions in Common.php | |
+ - getNextId | |
+ - getPreviousId | |
+ - getLeftId | |
+ - getRightId | |
+ - getFirstRootId | |
+ - getRootId | |
+ - getChildId | |
+* Common.php merged with Tree.php | |
+* From now one use $foo = $tree->getParent(); echo $foo['id']; to get the same effect as getParentId(). | |
+ Note, that's just what getParentId did, we just removed the extra wrapper around it this way. | |
+* removed buildStructure, most of it's functionallity has been merged with _setup, and | |
+ the structure array is no longer multi dimensional | |
+* getNext renamed to nextSibling and getPrevious renamed to previousSibling to describe their functionality better | |
+* OptionsMDB.php and OptionsDB.php removed | |
+* getChild removed, use getChildren($id, true) instead (note, $oneChild is a new param so $levels has been moved back) | |
+ the signature is now: function getChildren($ids, $levels = 1, $oneChild = false) | |
+* getNode renamed to getBranch to reflect it's purpose better | |
+ | |
</notes> | |
<contents> | |
<dir name="/"> | |
<dir name="Tree"> | |
<dir name="Dynamic"> | |
- <file baseinstalldir="Tree" name="DBnested.php" role="php" /> | |
- <file baseinstalldir="Tree" name="MDBnested.php" role="php" /> | |
- <file baseinstalldir="Tree" name="MDB2nested.php" role="php" /> | |
+ <file baseinstalldir="Tree" name="SQLnested.php" role="php" /> | |
</dir> <!-- /Dynamic --> | |
<dir name="Memory"> | |
<file baseinstalldir="Tree" name="Array.php" role="php" /> | |
- <file baseinstalldir="Tree" name="DBnested.php" role="php" /> | |
- <file baseinstalldir="Tree" name="DBsimple.php" role="php" /> | |
- <file baseinstalldir="Tree" name="MDBnested.php" role="php" /> | |
- <file baseinstalldir="Tree" name="MDBsimple.php" role="php" /> | |
- <file baseinstalldir="Tree" name="MDB2nested.php" role="php" /> | |
- <file baseinstalldir="Tree" name="MDB2simple.php" role="php" /> | |
<file baseinstalldir="Tree" name="Filesystem.php" role="php" /> | |
+ <file baseinstalldir="Tree" name="SQLnested.php" role="php" /> | |
+ <file baseinstalldir="Tree" name="SQLsimple.php" role="php" /> | |
<file baseinstalldir="Tree" name="XML.php" role="php" /> | |
</dir> <!-- /Memory --> | |
- <file baseinstalldir="Tree" name="Common.php" role="php" /> | |
- <file baseinstalldir="Tree" name="Error.php" role="php" /> | |
+ <dir name="Storage"> | |
+ <file baseinstalldir="Tree" name="DB.php" role="php" /> | |
+ <file baseinstalldir="Tree" name="MDB.php" role="php" /> | |
+ <file baseinstalldir="Tree" name="MDB2.php" role="php" /> | |
+ <file baseinstalldir="Tree" name="SQL.php" role="php" /> | |
+ </dir> <!-- /Storage --> | |
<file baseinstalldir="Tree" name="Memory.php" role="php" /> | |
- <file baseinstalldir="Tree" name="OptionsDB.php" role="php" /> | |
- <file baseinstalldir="Tree" name="OptionsMDB.php" role="php" /> | |
- <file baseinstalldir="Tree" name="OptionsMDB2.php" role="php" /> | |
+ <file baseinstalldir="Tree" name="Storage.php" role="php" /> | |
<file baseinstalldir="Tree" name="Tree.php" role="php" /> | |
- </dir> <!-- Tree --> | |
+ </dir> <!-- /Tree --> | |
<dir name="docs"> | |
<dir name="TreeEditor"> | |
<file baseinstalldir="Tree" name="closedFolder.gif" role="doc" /> | |
@@ -111,13 +112,14 @@ | |
</dir> <!-- /docs/TreeView --> | |
<file baseinstalldir="Tree" name="config.xml" role="doc" /> | |
<file baseinstalldir="Tree" name="Dynamic_DBnested.php" role="doc" /> | |
- <file baseinstalldir="Tree" name="Dynamic_DBnested.sql" role="doc" /> | |
+ <file baseinstalldir="Tree" name="Dynamic_MDBnested.php" role="doc" /> | |
+ <file baseinstalldir="Tree" name="funcs.php" role="doc" /> | |
<file baseinstalldir="Tree" name="Memory_DBnested.php" role="doc" /> | |
<file baseinstalldir="Tree" name="Memory_DBsimple.php" role="doc" /> | |
- <file baseinstalldir="Tree" name="Dynamic_MDBnested.php" role="doc" /> | |
<file baseinstalldir="Tree" name="Memory_MDBnested.php" role="doc" /> | |
<file baseinstalldir="Tree" name="Memory_MDBsimple.php" role="doc" /> | |
<file baseinstalldir="Tree" name="Memory_XML.php" role="doc" /> | |
+ <file baseinstalldir="Tree" name="nested_tree.sql" role="doc" /> | |
</dir> <!-- /docs --> | |
<dir name="tests"> | |
<file baseinstalldir="Tree" name="AllTests.php" role="test" /> | |
@@ -162,102 +164,9 @@ | |
</optional> | |
</dependencies> | |
<phprelease /> | |
- | |
<changelog> | |
- | |
<release> | |
- <date>2009-03-12</date> | |
- <time>14:12:08</time> | |
- <version> | |
- <release>0.3.4</release> | |
- <api>0.3.4</api> | |
- </version> | |
- <stability> | |
- <release>beta</release> | |
- <api>beta</api> | |
- </stability> | |
- <license uri="http://www.php.net/license">PHP License</license> | |
- <notes> | |
-* Fix Bug #14710: trailing spaces in files [dufuz] | |
- </notes> | |
- </release> | |
- | |
- <release> | |
- <date>2008-03-23</date> | |
- <time>14:12:08</time> | |
- <version> | |
- <release>0.3.3</release> | |
- <api>0.3.3</api> | |
- </version> | |
- <stability> | |
- <release>beta</release> | |
- <api>beta</api> | |
- </stability> | |
- <license uri="http://www.php.net/license">PHP License</license> | |
- <notes> | |
- * Fixed Bug #11822 package description should include mention of MDB2 compatibility | |
- * Fixed Bug #11853 Dynamic_MDB2nested uses undefined functions | |
- * Fixed Bug #12780 DB connection instead DSN fails because of get_parent_class | |
- * Fixed Bug #13080 MDB2simple _setup(): parentId cleared if parentId column is mapped to "parentid" | |
- * Fixed Bug #13081 Reopen #11504: MDB2+Tree problem. MDB2 doesn't contains getTextValue method | |
- </notes> | |
- </release> | |
- | |
- <release> | |
- <date>2008-03-23</date> | |
- <time>14:12:08</time> | |
- <version> | |
- <release>0.3.3</release> | |
- <api>0.3.3</api> | |
- </version> | |
- <stability> | |
- <release>beta</release> | |
- <api>beta</api> | |
- </stability> | |
- <license uri="http://www.php.net/license">PHP License</license> | |
- <notes> | |
- * Fixed Bug #11822 package description should include mention of MDB2 compatibility | |
- * Fixed Bug #11853 Dynamic_MDB2nested uses undefined functions | |
- * Fixed Bug #12780 DB connection instead DSN fails because of get_parent_class | |
- * Fixed Bug #13080 MDB2simple _setup(): parentId cleared if parentId column is mapped to "parentid" | |
- * Fixed Bug #13081 Reopen #11504: MDB2+Tree problem. MDB2 doesn't contains getTextValue method | |
- </notes> | |
- </release> | |
- <release> | |
- <date>2007-08-11</date> | |
- <time>14:12:08</time> | |
- <version> | |
- <release>0.3.2</release> | |
- <api>0.3.2</api> | |
- </version> | |
- <stability> | |
- <release>beta</release> | |
- <api>beta</api> | |
- </stability> | |
- <license uri="http://www.php.net/license">PHP License</license> | |
- <notes> | |
- * Fix Bug #11504 MDB2+Tree problem. MDB2 doesn't contains getTextValue method, patch by Simon Ruderich | |
- * Fix Bug #11500 Tree/Memory.php method getElementContent() not working, patch by Simon Ruderich | |
- </notes> | |
- </release> | |
- <release> | |
- <date>2007-06-23</date> | |
- <time>14:12:08</time> | |
- <version> | |
- <release>0.3.2</release> | |
- <api>0.3.2</api> | |
- </version> | |
- <stability> | |
- <release>beta</release> | |
- <api>beta</api> | |
- </stability> | |
- <license uri="http://www.php.net/license">PHP License</license> | |
- <notes> | |
-* Fix Bug #11365 Tree class doesnt contains raiseError method | |
- </notes> | |
- </release> | |
- <release> | |
- <date>2007-06-02</date> | |
+<date>2007-06-02</date> | |
<time>14:12:08</time> | |
<version> | |
<release>0.3.0</release> | |
@@ -272,7 +181,7 @@ | |
* added parameter to getPathAsString(), which takes the key you want to have in the path | |
* add method getLevel() to Tree_Common, so it is also available for Dynamic_*, thanks to Michael Johnson | |
* Fixed bug #1976 Missing $this-> with __construct() (helgi) | |
-* Fixed bug #900 PEAR QA: improvement for get_class()-usage (helgi) | |
+* Fixed bug #900 PEAR QA: improvement for get_class()-usage (helgi) | |
* Fixed Bug #913 MDB Container + fixes (lorzenzo thanks! helgi) | |
* Fixed Bug #1569 Tree_Memory_DBsimple has no hasChildren function hence remove doesnt work (helgi) | |
* Fixed Bug #4803 References fix (patch from yunosh aka. Jan Schneider) | |
@@ -280,7 +189,7 @@ | |
* add unit test, at least for all new/modified methods | |
* CS fixes | |
* package xml version 2 | |
- | |
+ | |
</notes> | |
</release> | |
<release> | |
@@ -295,7 +204,7 @@ | |
<date>2003-03-17</date> | |
<license uri="http://www.php.net/license">PHP License</license> | |
<notes>* bugfix in Memory_Array::add method, which made the last element being added in a bogus way | |
- | |
+ | |
</notes> | |
</release> | |
<release> | |
@@ -326,7 +235,7 @@ | |
* Make setup work with custom data optionally (only relevant for Memory_*) | |
* Show a nicer varDump | |
* add UML class diagram | |
- | |
+ | |
</notes> | |
</release> | |
<release> | |
Property changes on: package.xml | |
___________________________________________________________________ | |
Modified: cvs2svn:cvs-rev | |
## -1 +1 ## | |
-1.36.2.9 | |
+1.37 | |
Index: . | |
=================================================================== | |
--- . (.../branches/Tree_0_3_0) (revision 321102) | |
+++ . (.../trunk) (revision 321102) | |
Property changes on: . | |
___________________________________________________________________ | |
Deleted: svn:mergeinfo | |
Reverse-merged /pear/packages/Tree/trunk:r320621-320622 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment