Source for file NestedSet.php
Documentation is available at NestedSet.php
* $Id: NestedSet.php 2230 2007-08-14 16:37:48Z Jonathan.Wage $
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.phpdoctrine.com>.
* Doctrine_Tree_NestedSet
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @version $Revision: 2230 $
* @author Joe Simms <joe.simms@websites4.com>
* constructor, creates tree with reference to table and sets default root options
* @param object $table instance of Doctrine_Table
* @param array $options options
public function __construct(Doctrine_Table $table, $options)
// set default many root attributes
$options['hasManyRoots'] = isset
($options['hasManyRoots']) ?
$options['hasManyRoots'] :
false;
if($options['hasManyRoots'])
$options['rootColumnName'] = isset
($options['rootColumnName']) ?
$options['rootColumnName'] :
'root_id';
* used to define table attributes required for the NestetSet implementation
* adds lft and rgt columns for corresponding left and right values
$this->table->setColumn($root, 'integer', 4);
$this->table->setColumn('lft', 'integer', 4);
$this->table->setColumn('rgt', 'integer', 4);
$this->table->setColumn('level', 'integer', 2);
* creates root node from given record or from a new record
* @param object $record instance of Doctrine_Record
public function createRoot(Doctrine_Record $record =
null)
$record =
$this->table->create();
// if tree is many roots, and no root id has been set, then get next root id
if ($root =
$this->getAttribute('hasManyRoots') &&
$record->getNode()->getRootValue() <=
0) {
$record->set('lft', '1');
$record->set('rgt', '2');
$record->set('level', 0);
* @return object $record instance of Doctrine_Record
* @deprecated Use fetchRoot()
* Fetches a/the root node.
$q =
$q->addWhere($this->_baseAlias .
'.lft = ?', 1);
// if tree has many roots, then specify root id
$root =
$data->getFirst();
* @param array $options Options
* @return mixed The tree or FALSE if the tree could not be found.
public function fetchTree($options =
array())
$q =
$q->addWhere($this->_baseAlias .
".lft >= ?", 1);
// if tree has many roots, then specify root id
$rootId = isset
($options['root_id']) ?
$options['root_id'] :
'1';
* Fetches a branch of a tree.
* @param mixed $pk primary key as used by table::find() to locate node to traverse tree from
* @param array $options Options.
* @return mixed The branch or FALSE if the branch could not be found.
* @todo Only fetch the lft and rgt values of the initial record. more is not needed.
$record =
$this->table->find($pk);
// TODO: if record doesn't exist, throw exception or similar?
//$depth = isset($options['depth']) ? $options['depth'] : null;
$params =
array($record->get('lft'), $record->get('rgt'));
* Fetches all root nodes. If the tree has only one root this is the same as
* @return mixed The root nodes.
$q =
$q->addWhere($this->_baseAlias .
'.lft = ?', 1);
* calculates the next available root id
* calculates the current max root id
$component =
$this->table->getComponentName();
// cannot get this dql to work, cannot retrieve result using $coll[0]->max
//$dql = "SELECT MAX(c.$column) FROM $component c";
$dql =
'SELECT c.' .
$column .
' FROM ' .
$component .
' c ORDER BY c.' .
$column .
' DESC LIMIT 1';
$coll =
$this->table->getConnection()->query($dql);
$max =
$coll[0]->get($column);
* returns parsed query with root id where clause added if applicable
* @param object $query Doctrine_Query
* @param integer $root_id id of destination root
* @return object Doctrine_Query
$query->addWhere($root .
' = ?', $rootId);
* Enter description here...
* Enter description here...
* Enter description here...
* Enter description here...
* @param Doctrine_Query $query
* Enter description here...
* Enter description here...
* @param unknown_type $graph
public function computeLevels($tree)
$isArray = is_array($tree);
$rootColumnName = $this->getAttribute('rootColumnName');
for ($i = 0, $count = count($tree); $i < $count; $i++) {
if ($rootColumnName && $i > 0 && $tree[$i][$rootColumnName] != $tree[$i-1][$rootColumnName]) {
while (count($right) > 0 && $right[count($right)-1] < $tree[$i]['rgt']) {
$tree[$i]['level'] = count($right);
$tree[$i]->getNode()->setLevel(count($right));
$right[] = $tree[$i]['rgt'];