1728 lines
51 KiB
PHP
1728 lines
51 KiB
PHP
<?php
|
|
|
|
/**
|
|
* This file is part of the Propel package.
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*
|
|
* @license MIT License
|
|
*/
|
|
|
|
require_once 'builder/om/PeerBuilder.php';
|
|
|
|
/**
|
|
* Generates a PHP5 tree nested set Peer class for user object model (OM).
|
|
*
|
|
* This class produces the base tree nested set object class (e.g. BaseMyTable) which contains all
|
|
* the custom-built accessor and setter methods.
|
|
*
|
|
* This class replaces the Node.tpl, with the intent of being easier for users
|
|
* to customize (through extending & overriding).
|
|
*
|
|
* @author heltem <heltem@o2php.com>
|
|
* @package propel.generator.builder.om
|
|
*/
|
|
class PHP5NestedSetPeerBuilder extends PeerBuilder
|
|
{
|
|
|
|
/**
|
|
* Gets the package for the [base] object classes.
|
|
* @return string
|
|
*/
|
|
public function getPackage()
|
|
{
|
|
return parent::getPackage() . ".om";
|
|
}
|
|
|
|
/**
|
|
* Returns the name of the current class being built.
|
|
* @return string
|
|
*/
|
|
public function getUnprefixedClassname()
|
|
{
|
|
return $this->getBuildProperty('basePrefix') . $this->getStubObjectBuilder()->getUnprefixedClassname() . 'NestedSetPeer';
|
|
}
|
|
|
|
/**
|
|
* Adds the include() statements for files that this class depends on or utilizes.
|
|
* @param string &$script The script will be modified in this method.
|
|
*/
|
|
protected function addIncludes(&$script)
|
|
{
|
|
$script .="
|
|
require '".$this->getPeerBuilder()->getClassFilePath()."';
|
|
";
|
|
} // addIncludes()
|
|
|
|
/**
|
|
* Adds class phpdoc comment and openning of class.
|
|
* @param string &$script The script will be modified in this method.
|
|
*/
|
|
protected function addClassOpen(&$script)
|
|
{
|
|
|
|
$table = $this->getTable();
|
|
$tableName = $table->getName();
|
|
$tableDesc = $table->getDescription();
|
|
|
|
$script .= "
|
|
/**
|
|
* Base static class for performing query operations on the tree contained by the '$tableName' table.
|
|
*
|
|
* $tableDesc
|
|
*";
|
|
if ($this->getBuildProperty('addTimeStamp')) {
|
|
$now = strftime('%c');
|
|
$script .= "
|
|
* This class was autogenerated by Propel " . $this->getBuildProperty('version') . " on:
|
|
*
|
|
* $now
|
|
*";
|
|
}
|
|
$script .= "
|
|
* @deprecated Since Propel 1.5. Use the nested_set behavior instead of the NestedSet treeMode
|
|
* @package propel.generator.".$this->getPackage()."
|
|
*/
|
|
abstract class ".$this->getClassname()." extends ".$this->getPeerBuilder()->getClassName()." implements NodePeer {
|
|
";
|
|
}
|
|
|
|
/**
|
|
* Specifies the methods that are added as part of the basic OM class.
|
|
* This can be overridden by subclasses that wish to add more methods.
|
|
* @see ObjectBuilder::addClassBody()
|
|
*/
|
|
protected function addClassBody(&$script)
|
|
{
|
|
$table = $this->getTable();
|
|
|
|
// FIXME
|
|
// - Probably the build needs to be customized for supporting
|
|
// tables that are "aliases". -- definitely a fringe usecase, though.
|
|
|
|
$this->addConstants($script);
|
|
|
|
$this->addCreateRoot($script);
|
|
|
|
$this->addRetrieveRoot($script);
|
|
|
|
$this->addInsertAsFirstChildOf($script);
|
|
$this->addInsertAsLastChildOf($script);
|
|
$this->addInsertAsPrevSiblingOf($script);
|
|
$this->addInsertAsNextSiblingOf($script);
|
|
$this->addInsertAsParentOf($script);
|
|
|
|
$this->addInsertRoot($script);
|
|
$this->addInsertParent($script);
|
|
|
|
$this->addDeleteRoot($script);
|
|
$this->addDeleteNode($script);
|
|
|
|
$this->addMoveToFirstChildOf($script);
|
|
$this->addMoveToLastChildOf($script);
|
|
$this->addMoveToPrevSiblingOf($script);
|
|
$this->addMoveToNextSiblingOf($script);
|
|
|
|
$this->addRetrieveFirstChild($script);
|
|
$this->addRetrieveLastChild($script);
|
|
$this->addRetrievePrevSibling($script);
|
|
$this->addRetrieveNextSibling($script);
|
|
|
|
$this->addRetrieveTree($script);
|
|
$this->addRetrieveBranch($script);
|
|
$this->addRetrieveChildren($script);
|
|
$this->addRetrieveDescendants($script);
|
|
$this->addRetrieveSiblings($script);
|
|
$this->addRetrieveParent($script);
|
|
|
|
$this->addGetLevel($script);
|
|
$this->addGetNumberOfChildren($script);
|
|
$this->addGetNumberOfDescendants($script);
|
|
$this->addGetPath($script);
|
|
|
|
$this->addIsValid($script);
|
|
$this->addIsRoot($script);
|
|
$this->addIsLeaf($script);
|
|
$this->addIsChildOf($script);
|
|
$this->addIsChildOfOrSiblingTo($script);
|
|
$this->addIsEqualTo($script);
|
|
|
|
$this->addHasParent($script);
|
|
$this->addHasPrevSibling($script);
|
|
$this->addHasNextSibling($script);
|
|
$this->addHasChildren($script);
|
|
|
|
$this->addDeleteDescendants($script);
|
|
|
|
$this->addGetNode($script);
|
|
|
|
$this->addHydrateDescendants($script);
|
|
$this->addHydrateChildren($script);
|
|
|
|
$this->addShiftRParent($script);
|
|
$this->addUpdateLoadedNode($script);
|
|
$this->addUpdateDBNode($script);
|
|
|
|
$this->addShiftRLValues($script);
|
|
$this->addShiftRLRange($script);
|
|
}
|
|
|
|
/**
|
|
* Closes class.
|
|
* @param string &$script The script will be modified in this method.
|
|
*/
|
|
protected function addClassClose(&$script)
|
|
{
|
|
$script .= "
|
|
} // " . $this->getClassname() . "
|
|
";
|
|
}
|
|
|
|
protected function addConstants(&$script)
|
|
{
|
|
$table = $this->getTable();
|
|
$tableName = $table->getName();
|
|
|
|
$colname = array();
|
|
|
|
foreach ($table->getColumns() as $col) {
|
|
if ($col->isNestedSetLeftKey()) {
|
|
$colname['left'] = $tableName . '.' . strtoupper($col->getName());
|
|
}
|
|
|
|
if ($col->isNestedSetRightKey()) {
|
|
$colname['right'] = $tableName . '.' . strtoupper($col->getName());
|
|
}
|
|
|
|
if ($col->isTreeScopeKey()) {
|
|
$colname['scope'] = $tableName . '.' . strtoupper($col->getName());
|
|
}
|
|
|
|
if (3 == count($colname)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!isset($colname['left'])) {
|
|
throw new EngineException("One column must have nestedSetLeftKey attribute set to true for [" . $table->getName() . "] table");
|
|
}
|
|
|
|
if(!isset($colname['right'])) {
|
|
throw new EngineException("One column must have nestedSetRightKey attribute set to true for [" . $table->getName() . "] table");
|
|
}
|
|
|
|
$colname['scope'] = isset($colname['scope']) ? $colname['scope'] : null;
|
|
|
|
$script .= "
|
|
/**
|
|
* Left column for the set
|
|
*/
|
|
const LEFT_COL = " . var_export($colname['left'], true) . ";
|
|
|
|
/**
|
|
* Right column for the set
|
|
*/
|
|
const RIGHT_COL = " . var_export($colname['right'], true) . ";
|
|
|
|
/**
|
|
* Scope column for the set
|
|
*/
|
|
const SCOPE_COL = " . var_export($colname['scope'], true) . ";
|
|
";
|
|
}
|
|
|
|
protected function addCreateRoot(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Creates the supplied node as the root node.
|
|
*
|
|
* @param $objectClassname \$node Propel object for model
|
|
* @throws PropelException
|
|
*/
|
|
public static function createRoot(NodeObject \$node)
|
|
{
|
|
if (\$node->getLeftValue()) {
|
|
throw new PropelException('Cannot turn an existing node into a root node.');
|
|
}
|
|
|
|
\$node->setLeftValue(1);
|
|
\$node->setRightValue(2);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveRoot(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Returns the root node for a given scope id
|
|
*
|
|
* @param int \$scopeId Scope id to determine which root node to return
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return $objectClassname Propel object for root node
|
|
*/
|
|
public static function retrieveRoot(\$scopeId = null, PropelPDO \$con = null)
|
|
{
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
|
|
\$c->add(self::LEFT_COL, 1, Criteria::EQUAL);
|
|
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$scopeId, Criteria::EQUAL);
|
|
}
|
|
|
|
return $peerClassname::doSelectOne(\$c, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addInsertAsFirstChildOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Inserts \$child as first child of given \$parent node
|
|
*
|
|
* @param $objectClassname \$child Propel object for child node
|
|
* @param $objectClassname \$parent Propel object for parent node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function insertAsFirstChildOf(NodeObject \$child, NodeObject \$parent, PropelPDO \$con = null)
|
|
{
|
|
// Update \$child node properties
|
|
\$child->setLeftValue(\$parent->getLeftValue() + 1);
|
|
\$child->setRightValue(\$parent->getLeftValue() + 2);
|
|
\$child->setParentNode(\$parent);
|
|
|
|
\$sidv = null;
|
|
if (self::SCOPE_COL) {
|
|
\$child->setScopeIdValue(\$sidv = \$parent->getScopeIdValue());
|
|
}
|
|
|
|
// Update database nodes
|
|
self::shiftRLValues(\$child->getLeftValue(), 2, \$con, \$sidv);
|
|
|
|
// Update all loaded nodes
|
|
self::updateLoadedNode(\$parent, 2, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addInsertAsLastChildOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Inserts \$child as last child of destination node \$parent
|
|
*
|
|
* @param $objectClassname \$child Propel object for child node
|
|
* @param $objectClassname \$parent Propel object for parent node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function insertAsLastChildOf(NodeObject \$child, NodeObject \$parent, PropelPDO \$con = null)
|
|
{
|
|
// Update \$child node properties
|
|
\$child->setLeftValue(\$parent->getRightValue());
|
|
\$child->setRightValue(\$parent->getRightValue() + 1);
|
|
\$child->setParentNode(\$parent);
|
|
|
|
\$sidv = null;
|
|
if (self::SCOPE_COL) {
|
|
\$child->setScopeIdValue(\$sidv = \$parent->getScopeIdValue());
|
|
}
|
|
|
|
// Update database nodes
|
|
self::shiftRLValues(\$child->getLeftValue(), 2, \$con, \$sidv);
|
|
|
|
// Update all loaded nodes
|
|
self::updateLoadedNode(\$parent, 2, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addInsertAsPrevSiblingOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Inserts \$sibling as previous sibling to destination node \$node
|
|
*
|
|
* @param $objectClassname \$node Propel object for destination node
|
|
* @param $objectClassname \$sibling Propel object for source node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function insertAsPrevSiblingOf(NodeObject \$node, NodeObject \$sibling, PropelPDO \$con = null)
|
|
{
|
|
if (\$sibling->isRoot()) {
|
|
throw new PropelException('Root nodes cannot have siblings');
|
|
}
|
|
|
|
\$node->setLeftValue(\$sibling->getLeftValue());
|
|
\$node->setRightValue(\$sibling->getLeftValue() + 1);
|
|
\$node->setParentNode(\$sibling->retrieveParent());
|
|
|
|
\$sidv = null;
|
|
if (self::SCOPE_COL) {
|
|
\$node->setScopeIdValue(\$sidv = \$sibling->getScopeIdValue());
|
|
}
|
|
|
|
// Update database nodes
|
|
self::shiftRLValues(\$node->getLeftValue(), 2, \$con, \$sidv);
|
|
|
|
// Update all loaded nodes
|
|
self::updateLoadedNode(\$sibling->retrieveParent(), 2, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addInsertAsNextSiblingOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Inserts \$sibling as next sibling to destination node \$node
|
|
*
|
|
* @param $objectClassname \$node Propel object for destination node
|
|
* @param $objectClassname \$sibling Propel object for source node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function insertAsNextSiblingOf(NodeObject \$node, NodeObject \$sibling, PropelPDO \$con = null)
|
|
{
|
|
if (\$sibling->isRoot()) {
|
|
throw new PropelException('Root nodes cannot have siblings');
|
|
}
|
|
|
|
\$node->setLeftValue(\$sibling->getRightValue() + 1);
|
|
\$node->setRightValue(\$sibling->getRightValue() + 2);
|
|
\$node->setParentNode(\$sibling->retrieveParent());
|
|
|
|
\$sidv = null;
|
|
if (self::SCOPE_COL) {
|
|
\$node->setScopeIdValue(\$sidv = \$sibling->getScopeIdValue());
|
|
}
|
|
|
|
// Update database nodes
|
|
self::shiftRLValues(\$node->getLeftValue(), 2, \$con, \$sidv);
|
|
|
|
// Update all loaded nodes
|
|
self::updateLoadedNode(\$sibling->retrieveParent(), 2, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addInsertAsParentOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Inserts \$parent as parent of given node.
|
|
*
|
|
* @param $objectClassname \$parent Propel object for given parent node
|
|
* @param $objectClassname \$node Propel object for given destination node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function insertAsParentOf(NodeObject \$parent, NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$sidv = null;
|
|
if (self::SCOPE_COL) {
|
|
\$sidv = \$node->getScopeIdValue();
|
|
}
|
|
|
|
self::shiftRLValues(\$node->getLeftValue(), 1, \$con, \$sidv);
|
|
self::shiftRLValues(\$node->getRightValue() + 2, 1, \$con, \$sidv);
|
|
|
|
if (self::SCOPE_COL) {
|
|
\$parent->setScopeIdValue(\$sidv);
|
|
}
|
|
|
|
\$parent->setLeftValue(\$node->getLeftValue());
|
|
\$parent->setRightValue(\$node->getRightValue() + 2);
|
|
|
|
\$previous_parent = \$node->retrieveParent();
|
|
\$parent->setParentNode(\$previous_parent);
|
|
\$node->setParentNode(\$parent);
|
|
|
|
\$node->save(\$con);
|
|
|
|
// Update all loaded nodes
|
|
self::updateLoadedNode(\$previous_parent, 2, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addInsertRoot(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Inserts \$node as root node
|
|
*
|
|
* @param $objectClassname \$node Propel object as root node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function insertRoot(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$sidv = null;
|
|
if (self::SCOPE_COL) {
|
|
\$sidv = \$node->getScopeIdValue();
|
|
}
|
|
|
|
$peerClassname::insertAsParentOf($peerClassname::retrieveRoot(\$sidv, \$con), \$node, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addInsertParent(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Inserts \$parent as parent to destination node \$child
|
|
*
|
|
* @deprecated 1.3 - 2007/11/06
|
|
* @see insertAsParentOf()
|
|
* @param $objectClassname \$child Propel object to become child node
|
|
* @param $objectClassname \$parent Propel object as parent node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function insertParent(NodeObject \$child, NodeObject \$parent, PropelPDO \$con = null)
|
|
{
|
|
self::insertAsParentOf(\$parent, \$child, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addDeleteRoot(&$script)
|
|
{
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Delete root node
|
|
*
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return boolean Deletion status
|
|
*/
|
|
public static function deleteRoot(\$scopeId = null, PropelPDO \$con = null)
|
|
{
|
|
if (!self::SCOPE_COL) {
|
|
\$scopeId = null;
|
|
}
|
|
\$root = $peerClassname::retrieveRoot(\$scopeId, \$con);
|
|
if ($peerClassname::getNumberOfChildren(\$root) == 1) {
|
|
return $peerClassname::deleteNode(\$root, \$con);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addDeleteNode(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Delete \$dest node
|
|
*
|
|
* @param $objectClassname \$dest Propel object node to delete
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return boolean Deletion status
|
|
*/
|
|
public static function deleteNode(NodeObject \$dest, PropelPDO \$con = null)
|
|
{
|
|
if (\$dest->getLeftValue() == 1) {
|
|
// deleting root implies conditions (see deleteRoot() method)
|
|
return $peerClassname::deleteRoot(\$con);
|
|
}
|
|
|
|
\$sidv = null;
|
|
if (self::SCOPE_COL) {
|
|
\$sidv = \$dest->getScopeIdValue();
|
|
}
|
|
|
|
self::shiftRLRange(\$dest->getLeftValue(), \$dest->getRightValue(), -1, \$con, \$sidv);
|
|
self::shiftRLValues(\$dest->getRightValue() + 1, -2, \$con, \$sidv);
|
|
return \$dest->delete(\$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addMoveToFirstChildOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Moves \$child to be first child of \$parent
|
|
*
|
|
* @param $objectClassname \$parent Propel object for parent node
|
|
* @param $objectClassname \$child Propel object for child node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function moveToFirstChildOf(NodeObject \$parent, NodeObject \$child, PropelPDO \$con = null)
|
|
{
|
|
if (\$parent->getScopeIdValue() != \$child->getScopeIdValue()) {
|
|
throw new PropelException('Moving nodes across trees is not supported');
|
|
}
|
|
\$destLeft = \$parent->getLeftValue() + 1;
|
|
self::updateDBNode(\$child, \$destLeft, \$con);
|
|
|
|
// Update all loaded nodes
|
|
self::updateLoadedNode(\$parent, 2, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addMoveToLastChildOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Moves \$child to be last child of \$parent
|
|
*
|
|
* @param $objectClassname \$parent Propel object for parent node
|
|
* @param $objectClassname \$child Propel object for child node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function moveToLastChildOf(NodeObject \$parent, NodeObject \$child, PropelPDO \$con = null)
|
|
{
|
|
if (\$parent->getScopeIdValue() != \$child->getScopeIdValue()) {
|
|
throw new PropelException('Moving nodes across trees is not supported');
|
|
}
|
|
\$destLeft = \$parent->getRightValue();
|
|
self::updateDBNode(\$child, \$destLeft, \$con);
|
|
|
|
// Update all loaded nodes
|
|
self::updateLoadedNode(\$parent, 2, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addMoveToPrevSiblingOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Moves \$node to be prev sibling to \$dest
|
|
*
|
|
* @param $objectClassname \$dest Propel object for destination node
|
|
* @param $objectClassname \$node Propel object for source node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function moveToPrevSiblingOf(NodeObject \$dest, NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
if (\$dest->getScopeIdValue() != \$node->getScopeIdValue()) {
|
|
throw new PropelException('Moving nodes across trees is not supported');
|
|
}
|
|
\$destLeft = \$dest->getLeftValue();
|
|
self::updateDBNode(\$node, \$destLeft, \$con);
|
|
|
|
// Update all loaded nodes
|
|
self::updateLoadedNode(\$dest->retrieveParent(), 2, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addMoveToNextSiblingOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Moves \$node to be next sibling to \$dest
|
|
*
|
|
* @param $objectClassname \$dest Propel object for destination node
|
|
* @param $objectClassname \$node Propel object for source node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return void
|
|
*/
|
|
public static function moveToNextSiblingOf(NodeObject \$dest, NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
if (\$dest->getScopeIdValue() != \$node->getScopeIdValue()) {
|
|
throw new PropelException('Moving nodes across trees is not supported');
|
|
}
|
|
\$destLeft = \$dest->getRightValue();
|
|
\$destLeft = \$destLeft + 1;
|
|
self::updateDBNode(\$node, \$destLeft, \$con);
|
|
|
|
// Update all loaded nodes
|
|
self::updateLoadedNode(\$dest->retrieveParent(), 2, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveFirstChild(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets first child for the given node if it exists
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return mixed Propel object if exists else false
|
|
*/
|
|
public static function retrieveFirstChild(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$c->add(self::LEFT_COL, \$node->getLeftValue() + 1, Criteria::EQUAL);
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$node->getScopeIdValue(), Criteria::EQUAL);
|
|
}
|
|
|
|
return $peerClassname::doSelectOne(\$c, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveLastChild(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets last child for the given node if it exists
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return mixed Propel object if exists else false
|
|
*/
|
|
public static function retrieveLastChild(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$c->add(self::RIGHT_COL, \$node->getRightValue() - 1, Criteria::EQUAL);
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$node->getScopeIdValue(), Criteria::EQUAL);
|
|
}
|
|
|
|
return $peerClassname::doSelectOne(\$c, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrievePrevSibling(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets prev sibling for the given node if it exists
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return mixed Propel object if exists else null
|
|
*/
|
|
public static function retrievePrevSibling(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$c->add(self::RIGHT_COL, \$node->getLeftValue() - 1, Criteria::EQUAL);
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$node->getScopeIdValue(), Criteria::EQUAL);
|
|
}
|
|
\$prevSibling = $peerClassname::doSelectOne(\$c, \$con);
|
|
\$node->setPrevSibling(\$prevSibling);
|
|
return \$prevSibling;
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveNextSibling(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets next sibling for the given node if it exists
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return mixed Propel object if exists else false
|
|
*/
|
|
public static function retrieveNextSibling(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$c->add(self::LEFT_COL, \$node->getRightValue() + 1, Criteria::EQUAL);
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$node->getScopeIdValue(), Criteria::EQUAL);
|
|
}
|
|
\$nextSibling = $peerClassname::doSelectOne(\$c, \$con);
|
|
\$node->setNextSibling(\$nextSibling);
|
|
return \$nextSibling;
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveTree(&$script)
|
|
{
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Retrieves the entire tree from root
|
|
*
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
public static function retrieveTree(\$scopeId = null, PropelPDO \$con = null)
|
|
{
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$c->addAscendingOrderByColumn(self::LEFT_COL);
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$scopeId, Criteria::EQUAL);
|
|
}
|
|
\$stmt = $peerClassname::doSelectStmt(\$c, \$con);
|
|
if (false !== (\$row = \$stmt->fetch(PDO::FETCH_NUM))) {
|
|
\$omClass = $peerClassname::getOMClass(\$row, 0);
|
|
\$cls = substr('.'.\$omClass, strrpos('.'.\$omClass, '.') + 1);
|
|
|
|
\$key = ".$peerClassname."::getPrimaryKeyHashFromRow(\$row, 0);
|
|
if (null === (\$root = ".$peerClassname."::getInstanceFromPool(\$key))) {
|
|
" . $this->buildObjectInstanceCreationCode('$root', '$cls') . "
|
|
\$root->hydrate(\$row);
|
|
}
|
|
|
|
\$root->setLevel(0);
|
|
$peerClassname::hydrateDescendants(\$root, \$stmt);
|
|
$peerClassname::addInstanceToPool(\$root);
|
|
|
|
\$stmt->closeCursor();
|
|
return \$root;
|
|
}
|
|
return false;
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveBranch(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Retrieves the entire tree from parent \$node
|
|
*
|
|
* @param $objectClassname \$node Propel object for parent node
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
public static function retrieveBranch(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
return $peerClassname::retrieveDescendants(\$node, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveChildren(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets direct children for the node
|
|
*
|
|
* @param $objectClassname \$node Propel object for parent node
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
public static function retrieveChildren(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$c->addAscendingOrderByColumn(self::LEFT_COL);
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$node->getScopeIdValue(), Criteria::EQUAL);
|
|
}
|
|
\$c->add(self::LEFT_COL, \$node->getLeftValue(), Criteria::GREATER_THAN);
|
|
\$c->addAnd(self::RIGHT_COL, \$node->getRightValue(), Criteria::LESS_THAN);
|
|
\$stmt = $peerClassname::doSelectStmt(\$c, \$con);
|
|
|
|
return $peerClassname::hydrateChildren(\$node, \$stmt);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveDescendants(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets all descendants for the node
|
|
*
|
|
* @param $objectClassname \$node Propel object for parent node
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
public static function retrieveDescendants(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$c->addAscendingOrderByColumn(self::LEFT_COL);
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$node->getScopeIdValue(), Criteria::EQUAL);
|
|
}
|
|
\$c->add(self::LEFT_COL, \$node->getLeftValue(), Criteria::GREATER_THAN);
|
|
\$c->addAnd(self::RIGHT_COL, \$node->getRightValue(), Criteria::LESS_THAN);
|
|
\$stmt = $peerClassname::doSelectStmt(\$c, \$con);
|
|
|
|
return $peerClassname::hydrateDescendants(\$node, \$stmt);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveSiblings(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets all siblings for the node
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
public static function retrieveSiblings(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$parent = $peerClassname::retrieveParent(\$node, \$con);
|
|
\$siblings = $peerClassname::retrieveChildren(\$parent, \$con);
|
|
|
|
return \$siblings;
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addRetrieveParent(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets immediate ancestor for the given node if it exists
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return mixed Propel object if exists else null
|
|
*/
|
|
public static function retrieveParent(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$c1 = \$c->getNewCriterion(self::LEFT_COL, \$node->getLeftValue(), Criteria::LESS_THAN);
|
|
\$c2 = \$c->getNewCriterion(self::RIGHT_COL, \$node->getRightValue(), Criteria::GREATER_THAN);
|
|
|
|
\$c1->addAnd(\$c2);
|
|
|
|
\$c->add(\$c1);
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$node->getScopeIdValue(), Criteria::EQUAL);
|
|
}
|
|
\$c->addAscendingOrderByColumn(self::RIGHT_COL);
|
|
|
|
\$parent = $peerClassname::doSelectOne(\$c, \$con);
|
|
|
|
\$node->setParentNode(\$parent);
|
|
|
|
return \$parent;
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addGetLevel(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets level for the given node
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return int Level for the given node
|
|
*/
|
|
public static function getLevel(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
if (\$con === null) {
|
|
\$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_READ);
|
|
}
|
|
|
|
\$sql = \"SELECT COUNT(*) AS level FROM \" . self::TABLE_NAME . \" WHERE \" . self::LEFT_COL . \" < :left AND \" . self::RIGHT_COL . \" > :right\";
|
|
|
|
if (self::SCOPE_COL) {
|
|
\$sql .= ' AND ' . self::SCOPE_COL . ' = :scope';
|
|
}
|
|
|
|
\$stmt = \$con->prepare(\$sql);
|
|
\$stmt->bindValue(':left', \$node->getLeftValue(), PDO::PARAM_INT);
|
|
\$stmt->bindValue(':right', \$node->getRightValue(), PDO::PARAM_INT);
|
|
if (self::SCOPE_COL) {
|
|
\$stmt->bindValue(':scope', \$node->getScopeIdValue());
|
|
}
|
|
\$stmt->execute();
|
|
\$row = \$stmt->fetch();
|
|
return \$row['level'];
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addGetNumberOfChildren(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets number of direct children for given node
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return int Level for the given node
|
|
*/
|
|
public static function getNumberOfChildren(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$children = $peerClassname::retrieveChildren(\$node);
|
|
return count(\$children);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addGetNumberOfDescendants(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Gets number of descendants for given node
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return int Level for the given node
|
|
*/
|
|
public static function getNumberOfDescendants(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$right = \$node->getRightValue();
|
|
\$left = \$node->getLeftValue();
|
|
\$num = (\$right - \$left - 1) / 2;
|
|
return \$num;
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addGetPath(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Returns path to a specific node as an array, useful to create breadcrumbs
|
|
*
|
|
* @param $objectClassname \$node Propel object of node to create path to
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return array Array in order of heirarchy
|
|
*/
|
|
public static function getPath(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$criteria = new Criteria();
|
|
if (self::SCOPE_COL) {
|
|
\$criteria->add(self::SCOPE_COL, \$node->getScopeIdValue(), Criteria::EQUAL);
|
|
}
|
|
\$criteria->add(self::LEFT_COL, \$node->getLeftValue(), Criteria::LESS_EQUAL);
|
|
\$criteria->add(self::RIGHT_COL, \$node->getRightValue(), Criteria::GREATER_EQUAL);
|
|
\$criteria->addAscendingOrderByColumn(self::LEFT_COL);
|
|
|
|
return self::doSelect(\$criteria, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addIsValid(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if node is valid
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @return bool
|
|
*/
|
|
public static function isValid(NodeObject \$node = null)
|
|
{
|
|
if (is_object(\$node) && \$node->getRightValue() > \$node->getLeftValue()) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addIsRoot(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if node is a root
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @return bool
|
|
*/
|
|
public static function isRoot(NodeObject \$node)
|
|
{
|
|
return (\$node->getLeftValue()==1);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addIsLeaf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if node is a leaf
|
|
*
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @return bool
|
|
*/
|
|
public static function isLeaf(NodeObject \$node)
|
|
{
|
|
return ((\$node->getRightValue()-\$node->getLeftValue())==1);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addIsChildOf(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if \$child is a child of \$parent
|
|
*
|
|
* @param $objectClassname \$child Propel object for node
|
|
* @param $objectClassname \$parent Propel object for node
|
|
* @return bool
|
|
*/
|
|
public static function isChildOf(NodeObject \$child, NodeObject \$parent)
|
|
{
|
|
return ((\$child->getLeftValue()>\$parent->getLeftValue()) && (\$child->getRightValue()<\$parent->getRightValue()));
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addIsChildOfOrSiblingTo(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if \$node1 is a child of or equal to \$node2
|
|
*
|
|
* @deprecated 1.3 - 2007/11/09
|
|
* @param $objectClassname \$node1 Propel object for node
|
|
* @param $objectClassname \$node2 Propel object for node
|
|
* @return bool
|
|
*/
|
|
public static function isChildOfOrSiblingTo(NodeObject \$node1, NodeObject \$node2)
|
|
{
|
|
return ((\$node1->getLeftValue()>=\$node2->getLeftValue()) and (\$node1->getRightValue()<=\$node2->getRightValue()));
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addIsEqualTo(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if \$node1 is equal to \$node2
|
|
*
|
|
* @param $objectClassname \$node1 Propel object for node
|
|
* @param $objectClassname \$node2 Propel object for node
|
|
* @return bool
|
|
*/
|
|
public static function isEqualTo(NodeObject \$node1, NodeObject \$node2)
|
|
{
|
|
\$also = true;
|
|
if (self::SCOPE_COL) {
|
|
\$also = (\$node1->getScopeIdValue() === \$node2->getScopeIdValue());
|
|
}
|
|
return \$node1->getLeftValue() == \$node2->getLeftValue() && \$node1->getRightValue() == \$node2->getRightValue() && \$also;
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addHasParent(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if \$node has an ancestor
|
|
*
|
|
* @param $objectClassname \$node Propel object for node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return bool
|
|
*/
|
|
public static function hasParent(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
return $peerClassname::isValid($peerClassname::retrieveParent(\$node, \$con));
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addHasPrevSibling(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if \$node has prev sibling
|
|
*
|
|
* @param $objectClassname \$node Propel object for node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return bool
|
|
*/
|
|
public static function hasPrevSibling(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
return $peerClassname::isValid($peerClassname::retrievePrevSibling(\$node, \$con));
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addHasNextSibling(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if \$node has next sibling
|
|
*
|
|
* @param $objectClassname \$node Propel object for node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return bool
|
|
*/
|
|
public static function hasNextSibling(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
return $peerClassname::isValid($peerClassname::retrieveNextSibling(\$node, \$con));
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addHasChildren(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Tests if \$node has children
|
|
*
|
|
* @param $objectClassname \$node Propel object for node
|
|
* @return bool
|
|
*/
|
|
public static function hasChildren(NodeObject \$node)
|
|
{
|
|
return ((\$node->getRightValue()-\$node->getLeftValue())>1);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addDeleteDescendants(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Deletes \$node and all of its descendants
|
|
*
|
|
* @param $objectClassname \$node Propel object for source node
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
public static function deleteDescendants(NodeObject \$node, PropelPDO \$con = null)
|
|
{
|
|
\$left = \$node->getLeftValue();
|
|
\$right = \$node->getRightValue();
|
|
|
|
\$c = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$c1 = \$c->getNewCriterion(self::LEFT_COL, \$left, Criteria::GREATER_THAN);
|
|
\$c2 = \$c->getNewCriterion(self::RIGHT_COL, \$right, Criteria::LESS_THAN);
|
|
|
|
\$c1->addAnd(\$c2);
|
|
|
|
\$c->add(\$c1);
|
|
if (self::SCOPE_COL) {
|
|
\$c->add(self::SCOPE_COL, \$node->getScopeIdValue(), Criteria::EQUAL);
|
|
}
|
|
\$c->addAscendingOrderByColumn(self::RIGHT_COL);
|
|
|
|
\$result = $peerClassname::doDelete(\$c, \$con);
|
|
|
|
self::shiftRLValues(\$right + 1, \$left - \$right -1, \$con, \$node->getScopeIdValue());
|
|
|
|
return \$result;
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addGetNode(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Returns a node given its primary key or the node itself
|
|
*
|
|
* @param int/$objectClassname \$node Primary key/instance of required node
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return object Propel object for model
|
|
*/
|
|
public static function getNode(\$node, PropelPDO \$con = null)
|
|
{
|
|
if (is_object(\$node)) {
|
|
return \$node;
|
|
} else {
|
|
\$object = $peerClassname::retrieveByPK(\$node, \$con);
|
|
\$rtn = is_object(\$object) ? \$object : false;
|
|
return \$rtn;
|
|
}
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addHydrateDescendants(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$table = $this->getTable();
|
|
$script .= "
|
|
/**
|
|
* Hydrate recursively the descendants of the given node
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PDOStatement \$stmt Executed PDOStatement
|
|
*/
|
|
protected static function hydrateDescendants(NodeObject \$node, PDOStatement \$stmt)
|
|
{
|
|
\$descendants = array();
|
|
\$children = array();
|
|
\$prevSibling = null;
|
|
";
|
|
|
|
if (!$table->getChildrenColumn()) {
|
|
$script .= "
|
|
// set the class once to avoid overhead in the loop
|
|
\$cls = $peerClassname::getOMClass();
|
|
\$cls = substr('.'.\$cls, strrpos('.'.\$cls, '.') + 1);
|
|
";
|
|
}
|
|
|
|
$script .= "
|
|
while (\$row = \$stmt->fetch(PDO::FETCH_NUM)) {
|
|
\$key = ".$peerClassname."::getPrimaryKeyHashFromRow(\$row, 0);
|
|
if (null === (\$child = ".$peerClassname."::getInstanceFromPool(\$key))) {";
|
|
|
|
if ($table->getChildrenColumn()) {
|
|
$script .= "
|
|
// class must be set each time from the record row
|
|
\$cls = ".$peerClassname."::getOMClass(\$row, 0);
|
|
\$cls = substr('.'.\$cls, strrpos('.'.\$cls, '.') + 1);
|
|
";
|
|
}
|
|
|
|
$script .= "
|
|
" . $this->buildObjectInstanceCreationCode('$child', '$cls') . "
|
|
\$child->hydrate(\$row);
|
|
}
|
|
|
|
\$child->setLevel(\$node->getLevel() + 1);
|
|
\$child->setParentNode(\$node);
|
|
if (!empty(\$prevSibling)) {
|
|
\$child->setPrevSibling(\$prevSibling);
|
|
\$prevSibling->setNextSibling(\$child);
|
|
}
|
|
|
|
\$descendants[] = \$child;
|
|
|
|
if (\$child->hasChildren()) {
|
|
\$descendants = array_merge(\$descendants, $peerClassname::hydrateDescendants(\$child, \$stmt));
|
|
} else {
|
|
\$child->setChildren(array());
|
|
}
|
|
|
|
\$children[] = \$child;
|
|
\$prevSibling = \$child;
|
|
|
|
$peerClassname::addInstanceToPool(\$child);
|
|
if (\$child->getRightValue() + 1 == \$node->getRightValue()) {
|
|
\$child->setNextSibling(null);
|
|
break;
|
|
}
|
|
}
|
|
\$node->setChildren(\$children);
|
|
return \$descendants;
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addHydrateChildren(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$table = $this->getTable();
|
|
$script .= "
|
|
/**
|
|
* Hydrate the children of the given node
|
|
* @param $objectClassname \$node Propel object for src node
|
|
* @param PDOStatement \$stmt Executed PDOStatement
|
|
*/
|
|
protected static function hydrateChildren(NodeObject \$node, PDOStatement \$stmt)
|
|
{
|
|
\$children = array();
|
|
\$prevRight = 0;
|
|
";
|
|
|
|
if (!$table->getChildrenColumn()) {
|
|
$script .= "
|
|
// set the class once to avoid overhead in the loop
|
|
\$cls = $peerClassname::getOMClass();
|
|
\$cls = substr('.'.\$cls, strrpos('.'.\$cls, '.') + 1);
|
|
";
|
|
}
|
|
|
|
$script .= "
|
|
while (\$row = \$stmt->fetch(PDO::FETCH_NUM)) {
|
|
\$key = ".$peerClassname."::getPrimaryKeyHashFromRow(\$row, 0);
|
|
if (null === (\$child = ".$peerClassname."::getInstanceFromPool(\$key))) {";
|
|
|
|
if ($table->getChildrenColumn()) {
|
|
$script .= "
|
|
// class must be set each time from the record row
|
|
\$cls = ".$peerClassname."::getOMClass(\$row, 0);
|
|
\$cls = substr('.'.\$cls, strrpos('.'.\$cls, '.') + 1);
|
|
";
|
|
}
|
|
|
|
$script .= "
|
|
" . $this->buildObjectInstanceCreationCode('$child', '$cls') . "
|
|
\$child->hydrate(\$row);
|
|
}
|
|
|
|
\$child->setLevel(\$node->getLevel() + 1);
|
|
|
|
if (\$child->getRightValue() > \$prevRight) {
|
|
\$children[] = \$child;
|
|
\$prevRight = \$child->getRightValue();
|
|
}
|
|
|
|
if (\$child->getRightValue() + 1 == \$node->getRightValue()) {
|
|
break;
|
|
}
|
|
}
|
|
\$node->setChildren(\$children);
|
|
return \$children;
|
|
}
|
|
";
|
|
}
|
|
|
|
/**
|
|
* @deprecated 1.3 - 2008/03/11
|
|
* Won't be fixed, defect by design
|
|
* Never trust it
|
|
*/
|
|
protected function addShiftRParent(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Adds '\$delta' to all parent R values.
|
|
* '\$delta' can also be negative.
|
|
*
|
|
* @deprecated 1.3 - 2008/03/11
|
|
* @param $objectClassname \$node Propel object for parent node
|
|
* @param int \$delta Value to be shifted by, can be negative
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
protected static function shiftRParent(NodeObject \$node, \$delta, PropelPDO \$con = null)
|
|
{
|
|
if (\$node->hasParent(\$con)) {
|
|
\$parent = \$node->retrieveParent();
|
|
self::shiftRParent(\$parent, \$delta, \$con);
|
|
}
|
|
\$node->setRightValue(\$node->getRightValue() + \$delta);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addUpdateLoadedNode(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$table = $this->getTable();
|
|
|
|
$script .= "
|
|
/**
|
|
* Reload all already loaded nodes to sync them with updated db
|
|
*
|
|
* @param $objectClassname \$node Propel object for parent node
|
|
* @param int \$delta Value to be shifted by, can be negative
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
protected static function updateLoadedNode(NodeObject \$node, \$delta, PropelPDO \$con = null)
|
|
{
|
|
if (Propel::isInstancePoolingEnabled()) {
|
|
\$keys = array();
|
|
foreach (self::\$instances as \$obj) {
|
|
\$keys[] = \$obj->getPrimaryKey();
|
|
}
|
|
|
|
if (!empty(\$keys)) {
|
|
// We don't need to alter the object instance pool; we're just modifying these ones
|
|
// already in the pool.
|
|
\$criteria = new Criteria(self::DATABASE_NAME);";
|
|
if (count($table->getPrimaryKey()) === 1) {
|
|
$pkey = $table->getPrimaryKey();
|
|
$col = array_shift($pkey);
|
|
$script .= "
|
|
\$criteria->add(".$this->getColumnConstant($col).", \$keys, Criteria::IN);
|
|
";
|
|
} else {
|
|
$fields = array();
|
|
foreach ($table->getPrimaryKey() as $k => $col) {
|
|
$fields[] = $this->getColumnConstant($col);
|
|
};
|
|
$script .= "
|
|
|
|
// Loop on each instances in pool
|
|
foreach (\$keys as \$values) {
|
|
// Create initial Criterion
|
|
\$cton = \$criteria->getNewCriterion(" . $fields[0] . ", \$values[0]);";
|
|
unset($fields[0]);
|
|
foreach ($fields as $k => $col) {
|
|
$script .= "
|
|
|
|
// Create next criterion
|
|
\$nextcton = \$criteria->getNewCriterion(" . $col . ", \$values[$k]);
|
|
// And merge it with the first
|
|
\$cton->addAnd(\$nextcton);";
|
|
}
|
|
$script .= "
|
|
|
|
// Add final Criterion to Criteria
|
|
\$criteria->addOr(\$cton);
|
|
}";
|
|
}
|
|
|
|
$script .= "
|
|
\$stmt = $peerClassname::doSelectStmt(\$criteria, \$con);
|
|
while (\$row = \$stmt->fetch(PDO::FETCH_NUM)) {
|
|
\$key = $peerClassname::getPrimaryKeyHashFromRow(\$row, 0);
|
|
if (null !== (\$object = $peerClassname::getInstanceFromPool(\$key))) {";
|
|
$n = 0;
|
|
foreach ($table->getColumns() as $col) {
|
|
if ($col->isNestedSetLeftKey()) {
|
|
$script .= "
|
|
\$object->setLeftValue(\$row[$n]);";
|
|
} else if ($col->isNestedSetRightKey()) {
|
|
$script .= "
|
|
\$object->setRightValue(\$row[$n]);";
|
|
}
|
|
$n++;
|
|
}
|
|
$script .= "
|
|
}
|
|
}
|
|
\$stmt->closeCursor();
|
|
}
|
|
}
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addUpdateDBNode(&$script)
|
|
{
|
|
$objectClassname = $this->getStubObjectBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Move \$node and its children to location \$destLeft and updates rest of tree
|
|
*
|
|
* @param $objectClassname \$node Propel object for node to update
|
|
* @param int \$destLeft Destination left value
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
protected static function updateDBNode(NodeObject \$node, \$destLeft, PropelPDO \$con = null)
|
|
{
|
|
\$left = \$node->getLeftValue();
|
|
\$right = \$node->getRightValue();
|
|
|
|
\$treeSize = \$right - \$left +1;
|
|
|
|
self::shiftRLValues(\$destLeft, \$treeSize, \$con, \$node->getScopeIdValue());
|
|
|
|
if (\$left >= \$destLeft) { // src was shifted too?
|
|
\$left += \$treeSize;
|
|
\$right += \$treeSize;
|
|
}
|
|
|
|
// now there's enough room next to target to move the subtree
|
|
self::shiftRLRange(\$left, \$right, \$destLeft - \$left, \$con, \$node->getScopeIdValue());
|
|
|
|
// correct values after source
|
|
self::shiftRLValues(\$right + 1, -\$treeSize, \$con, \$node->getScopeIdValue());
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addShiftRLValues(&$script)
|
|
{
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Adds '\$delta' to all L and R values that are >= '\$first'. '\$delta' can also be negative.
|
|
*
|
|
* @param int \$first First node to be shifted
|
|
* @param int \$delta Value to be shifted by, can be negative
|
|
* @param PropelPDO \$con Connection to use.
|
|
*/
|
|
protected static function shiftRLValues(\$first, \$delta, PropelPDO \$con = null, \$scopeId = null)
|
|
{
|
|
if (\$con === null) {
|
|
\$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_WRITE);
|
|
}
|
|
|
|
\$leftUpdateCol = self::LEFT_COL;
|
|
\$rightUpdateCol = self::RIGHT_COL;
|
|
|
|
// Shift left column values
|
|
\$whereCriteria = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$criterion = \$whereCriteria->getNewCriterion(
|
|
self::LEFT_COL,
|
|
\$first,
|
|
Criteria::GREATER_EQUAL);
|
|
|
|
if (self::SCOPE_COL) {
|
|
\$criterion->addAnd(
|
|
\$whereCriteria->getNewCriterion(
|
|
self::SCOPE_COL,
|
|
\$scopeId,
|
|
Criteria::EQUAL));
|
|
}
|
|
\$whereCriteria->add(\$criterion);
|
|
|
|
\$valuesCriteria = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$valuesCriteria->add(
|
|
self::LEFT_COL,
|
|
array('raw' => \$leftUpdateCol . ' + ?', 'value' => \$delta),
|
|
Criteria::CUSTOM_EQUAL);
|
|
|
|
{$this->basePeerClassname}::doUpdate(\$whereCriteria, \$valuesCriteria, \$con);
|
|
|
|
// Shift right column values
|
|
\$whereCriteria = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$criterion = \$whereCriteria->getNewCriterion(
|
|
self::RIGHT_COL,
|
|
\$first,
|
|
Criteria::GREATER_EQUAL);
|
|
|
|
if (self::SCOPE_COL) {
|
|
\$criterion->addAnd(
|
|
\$whereCriteria->getNewCriterion(
|
|
self::SCOPE_COL,
|
|
\$scopeId,
|
|
Criteria::EQUAL));
|
|
}
|
|
\$whereCriteria->add(\$criterion);
|
|
|
|
\$valuesCriteria = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$valuesCriteria->add(
|
|
self::RIGHT_COL,
|
|
array('raw' => \$rightUpdateCol . ' + ?', 'value' => \$delta),
|
|
Criteria::CUSTOM_EQUAL);
|
|
|
|
{$this->basePeerClassname}::doUpdate(\$whereCriteria, \$valuesCriteria, \$con);
|
|
}
|
|
";
|
|
}
|
|
|
|
protected function addShiftRLRange(&$script)
|
|
{
|
|
$peerClassname = $this->getStubPeerBuilder()->getClassname();
|
|
$script .= "
|
|
/**
|
|
* Adds '\$delta' to all L and R values that are >= '\$first' and <= '\$last'.
|
|
* '\$delta' can also be negative.
|
|
*
|
|
* @param int \$first First node to be shifted (L value)
|
|
* @param int \$last Last node to be shifted (L value)
|
|
* @param int \$delta Value to be shifted by, can be negative
|
|
* @param PropelPDO \$con Connection to use.
|
|
* @return array Shifted L and R values
|
|
*/
|
|
protected static function shiftRLRange(\$first, \$last, \$delta, PropelPDO \$con = null, \$scopeId = null)
|
|
{
|
|
if (\$con === null) {
|
|
\$con = Propel::getConnection($peerClassname::DATABASE_NAME, Propel::CONNECTION_WRITE);
|
|
}
|
|
|
|
\$leftUpdateCol = substr(self::LEFT_COL, strrpos(self::LEFT_COL, '.') + 1);
|
|
\$rightUpdateCol = substr(self::RIGHT_COL, strrpos(self::RIGHT_COL, '.') + 1);
|
|
|
|
// Shift left column values
|
|
\$whereCriteria = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$criterion = \$whereCriteria->getNewCriterion(self::LEFT_COL, \$first, Criteria::GREATER_EQUAL);
|
|
\$criterion->addAnd(\$whereCriteria->getNewCriterion(self::LEFT_COL, \$last, Criteria::LESS_EQUAL));
|
|
if (self::SCOPE_COL) {
|
|
\$criterion->addAnd(\$whereCriteria->getNewCriterion(self::SCOPE_COL, \$scopeId, Criteria::EQUAL));
|
|
}
|
|
\$whereCriteria->add(\$criterion);
|
|
|
|
\$valuesCriteria = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$valuesCriteria->add(
|
|
self::LEFT_COL,
|
|
array('raw' => \$leftUpdateCol . ' + ?', 'value' => \$delta),
|
|
Criteria::CUSTOM_EQUAL);
|
|
|
|
{$this->basePeerClassname}::doUpdate(\$whereCriteria, \$valuesCriteria, \$con);
|
|
|
|
// Shift right column values
|
|
\$whereCriteria = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$criterion = \$whereCriteria->getNewCriterion(self::RIGHT_COL, \$first, Criteria::GREATER_EQUAL);
|
|
\$criterion->addAnd(\$whereCriteria->getNewCriterion(self::RIGHT_COL, \$last, Criteria::LESS_EQUAL));
|
|
if (self::SCOPE_COL) {
|
|
\$criterion->addAnd(\$whereCriteria->getNewCriterion(self::SCOPE_COL, \$scopeId, Criteria::EQUAL));
|
|
}
|
|
\$whereCriteria->add(\$criterion);
|
|
|
|
\$valuesCriteria = new Criteria($peerClassname::DATABASE_NAME);
|
|
\$valuesCriteria->add(
|
|
self::RIGHT_COL,
|
|
array('raw' => \$rightUpdateCol . ' + ?', 'value' => \$delta),
|
|
Criteria::CUSTOM_EQUAL);
|
|
|
|
{$this->basePeerClassname}::doUpdate(\$whereCriteria, \$valuesCriteria, \$con);
|
|
|
|
return array('left' => \$first + \$delta, 'right' => \$last + \$delta);
|
|
}
|
|
";
|
|
}
|
|
|
|
} // PHP5NestedSetPeerBuilder
|