getColumns() as $col) { if ($col->isNodeKey()) { $npath_colname = $table->getName() . '.' . strtoupper($col->getName()); $npath_phpname = $col->getPhpName(); $npath_len = $col->getSize(); $npath_sep = $col->getNodeKeySep(); break; } } $db = $table->getDatabase(); if($table->getPackage()) { $package = $table->getPackage(); } else { $package = $targetPackage; } echo '<' . '?' . 'php'; ?> require_once 'getPhpName()) ?>'; require_once 'getPhpName() . 'Node') ?>'; /** * Base static class for performing query operations on the tree contained by the * 'getPhpName() ?>' table. * * This class was autogenerated by Propel on: * * [] * * @package */ class getPhpName() ?>NodePeer { const NPATH_COLNAME = ''; const NPATH_PHPNAME = ''; const NPATH_SEP = ''; /** * Temp function for CodeBase hacks that will go away. */ public static function isCodeBase($con = null) { if ($con === null) $con = Propel::getConnection(getPhpName() ?>Peer::DATABASE_NAME); return (get_class($con) == 'ODBCConnection' && get_class($con->getAdapter()) == 'CodeBaseAdapter'); } /** * Create a new Node at the top of tree. This method will destroy any * existing root node (along with its children). * * Use at your own risk! * * @param getPhpName() ?> Object wrapped by new node. * @param Connection Connection to use. * @return getPhpName() ?>Node * @throws PropelException */ public static function createNewRootNode($obj, $con = null) { if ($con === null) $con = Propel::getConnection(getPhpName() ?>Peer::DATABASE_NAME); try { $con->begin(); self::deleteNodeSubTree('1', $con); $setNodePath = 'set' . self::NPATH_PHPNAME; $obj->$setNodePath('1'); $obj->save($con); $con->commit(); } catch (PropelException $e) { $con->rollback(); throw $e; } return new getPhpName() ?>Node($obj); } /** * Inserts a new Node at the top of tree. Any existing root node (along with * its children) will be made a child of the new root node. This is a * safer alternative to createNewRootNode(). * * @param getPhpName() ?> Object wrapped by new node. * @param Connection Connection to use. * @return getPhpName() ?>Node * @throws PropelException */ public static function insertNewRootNode($obj, $con = null) { if ($con === null) $con = Propel::getConnection(getPhpName() ?>Peer::DATABASE_NAME); try { $con->begin(); // Move root tree to an invalid node path. self::moveNodeSubTree('1', '0', $con); $setNodePath = 'set' . self::NPATH_PHPNAME; // Insert the new root node. $obj->$setNodePath('1'); $obj->save($con); // Move the old root tree as a child of the new root. self::moveNodeSubTree('0', '1' . self::NPATH_SEP . '1', $con); $con->commit(); } catch (PropelException $e) { $con->rollback(); throw $e; } return new getPhpName() ?>Node($obj); } /** * Retrieves an array of tree nodes based on specified criteria. Optionally * includes all parent and/or child nodes of the matching nodes. * * @param Criteria Criteria to use. * @param boolean True if ancestors should also be retrieved. * @param boolean True if descendants should also be retrieved. * @param Connection Connection to use. * @return array Array of root nodes. */ public static function retrieveNodes($criteria, $ancestors = false, $descendants = false, $con = null) { $criteria = self::buildFamilyCriteria($criteria, $ancestors, $descendants); $rs = getPhpName() ?>Peer::doSelectRS($criteria, $con); return self::populateNodes($rs, $criteria); } /** * Retrieves a tree node based on a primary key. Optionally includes all * parent and/or child nodes of the matching node. * * @param mixed getPhpName() ?> primary key (array for composite keys) * @param boolean True if ancestors should also be retrieved. * @param boolean True if descendants should also be retrieved. * @param Connection Connection to use. * @return getPhpName() ?>Node */ public static function retrieveNodeByPK($pk, $ancestors = false, $descendants = false, $con = null) { throw new PropelException('retrieveNodeByPK() not implemented yet.'); } /** * Retrieves a tree node based on a node path. Optionally includes all * parent and/or child nodes of the matching node. * * @param string Node path to retrieve. * @param boolean True if ancestors should also be retrieved. * @param boolean True if descendants should also be retrieved. * @param Connection Connection to use. * @return getPhpName() ?>Node */ public static function retrieveNodeByNP($np, $ancestors = false, $descendants = false, $con = null) { $criteria = new Criteria(getPhpName() ?>Peer::DATABASE_NAME); $criteria->add(self::NPATH_COLNAME, $np, Criteria::EQUAL); $criteria = self::buildFamilyCriteria($criteria, $ancestors, $descendants); $rs = getPhpName() ?>Peer::doSelectRS($criteria, $con); $nodes = self::populateNodes($rs, $criteria); return (count($nodes) == 1 ? $nodes[0] : null); } /** * Retrieves the root node. * * @param string Node path to retrieve. * @param boolean True if descendants should also be retrieved. * @param Connection Connection to use. * @return getPhpName() ?>Node */ public static function retrieveRootNode($descendants = false, $con = null) { return self::retrieveNodeByNP('1', false, $descendants, $con); } /** * Moves the node subtree at srcpath to the dstpath. This method is intended * for internal use by the BaseNode object. Note that it does not check for * preexisting nodes at the dstpath. It also does not update the node path * of any Node objects that might currently be in memory. * * Use at your own risk! * * @param string Source node path to move (root of the src subtree). * @param string Destination node path to move to (root of the dst subtree). * @param Connection Connection to use. * @return void * @throws PropelException * @todo This is currently broken for simulated "onCascadeDelete"s. * @todo Need to abstract the SQL better. The CONCAT sql function doesn't * seem to be standardized (i.e. mssql), so maybe it needs to be moved * to DBAdapter. */ public static function moveNodeSubTree($srcPath, $dstPath, $con = null) { if (substr($dstPath, 0, strlen($srcPath)) == $srcPath) throw new PropelException('Cannot move a node subtree within itself.'); if ($con === null) $con = Propel::getConnection(getPhpName() ?>Peer::DATABASE_NAME); /** * Example: * UPDATE table * SET npath = CONCAT('1.3', SUBSTRING(npath, 6, 74)) * WHERE npath = '1.2.2' OR npath LIKE '1.2.2.%' */ $npath = self::NPATH_COLNAME; //the following dot isn`t mean`t a nodeKeySeperator $setcol = substr($npath, strpos($npath, '.')+1); $setcollen = ; $db = Propel::getDb(getPhpName() ?>Peer::DATABASE_NAME); // if (getPhpName() ?>NodePeer::isCodeBase($con)) { // This is a hack to get CodeBase working. It will eventually be removed. // It is a workaround for the following CodeBase bug: // -Prepared statement parameters cannot be embedded in SQL functions (i.e. CONCAT) $sql = "UPDATE " . getPhpName() ?>Peer::TABLE_NAME . " " . "SET $setcol=" . $db->concatString("'$dstPath'", $db->subString($npath, strlen($srcPath)+1, $setcollen)) . " " . "WHERE $npath = '$srcPath' OR $npath LIKE '" . $srcPath . self::NPATH_SEP . "%'"; $con->executeUpdate($sql); } else { // $sql = "UPDATE " . getPhpName() ?>Peer::TABLE_NAME . " " . "SET $setcol=" . $db->concatString('?', $db->subString($npath, '?', '?')) . " " . "WHERE $npath = ? OR $npath LIKE ?"; $stmt = $con->prepareStatement($sql); $stmt->setString(1, $dstPath); $stmt->setInt(2, strlen($srcPath)+1); $stmt->setInt(3, $setcollen); $stmt->setString(4, $srcPath); $stmt->setString(5, $srcPath . self::NPATH_SEP . '%'); $stmt->executeUpdate(); // } // } /** * Deletes the node subtree at the specified node path from the database. * * @param string Node path to delete * @param Connection Connection to use. * @return void * @throws PropelException * @todo This is currently broken for simulated "onCascadeDelete"s. */ public static function deleteNodeSubTree($nodePath, $con = null) { if ($con === null) $con = Propel::getConnection(getPhpName() ?>Peer::DATABASE_NAME); /** * DELETE FROM table * WHERE npath = '1.2.2' OR npath LIKE '1.2.2.%' */ $criteria = new Criteria(getPhpName() ?>Peer::DATABASE_NAME); $criteria->add(self::NPATH_COLNAME, $nodePath, Criteria::EQUAL); $criteria->addOr(self::NPATH_COLNAME, $nodePath . self::NPATH_SEP . '%', Criteria::LIKE); // For now, we call BasePeer directly since getPhpName() ?>Peer tries to // do a cascade delete. // getPhpName() ?>Peer::doDelete($criteria, $con); BasePeer::doDelete($criteria, $con); } /** * Builds the criteria needed to retrieve node ancestors and/or descendants. * * @param Criteria Criteria to start with * @param boolean True if ancestors should be retrieved. * @param boolean True if descendants should be retrieved. * @return Criteria */ public static function buildFamilyCriteria($criteria, $ancestors = false, $descendants = false) { /* Example SQL to retrieve nodepath '1.2.3' with both ancestors and descendants: SELECT L.NPATH, L.LABEL, test.NPATH, UCASE(L.NPATH) FROM test L, test WHERE test.NPATH='1.2.3' AND (L.NPATH=SUBSTRING(test.NPATH, 1, LENGTH(L.NPATH)) OR test.NPATH=SUBSTRING(L.NPATH, 1, LENGTH(test.NPATH))) ORDER BY UCASE(L.NPATH) ASC */ if ($criteria === null) $criteria = new Criteria(getPhpName() ?>::DATABASE_NAME); if (!$criteria->getSelectColumns()) getPhpName() ?>Peer::addSelectColumns($criteria); if (($ancestors || $descendants) && $criteria->size()) { // If we are retrieving ancestors/descendants, we need to do a // self-join to locate them. The exception to this is if no search // criteria is specified. In this case we're retrieving all nodes // anyway, so there is no need to do a self-join. // The left-side of the self-join will contain the columns we'll // use to build node objects (target node records along with their // ancestors and/or descendants). The right-side of the join will // contain the target node records specified by the initial criteria. // These are used to match the appropriate ancestor/descendant on // the left. // Specify an alias for the left-side table to use. $criteria->addAlias('L', getPhpName() ?>Peer::TABLE_NAME); // Make sure we have select columns to begin with. if (!$criteria->getSelectColumns()) getPhpName() ?>Peer::addSelectColumns($criteria); // Replace any existing columns for the right-side table with the // left-side alias. $selectColumns = $criteria->getSelectColumns(); $criteria->clearSelectColumns(); foreach ($selectColumns as $colName) $criteria->addSelectColumn(str_replace(getPhpName() ?>Peer::TABLE_NAME, 'L', $colName)); $db = Propel::getDb($criteria->getDbName()); $a = null; $d = null; $npathL = getPhpName() ?>Peer::alias('L', self::NPATH_COLNAME); $npathR = self::NPATH_COLNAME; $npath_len = ; if ($ancestors) { // For ancestors, match left-side node paths which are contained // by right-side node paths. $a = $criteria->getNewCriterion($npathL, "$npathL=" . $db->subString($npathR, 1, $db->strLength($npathL), $npath_len), Criteria::CUSTOM); } if ($descendants) { // For descendants, match left-side node paths which contain // right-side node paths. $d = $criteria->getNewCriterion($npathR, "$npathR=" . $db->subString($npathL, 1, $db->strLength($npathR), $npath_len), Criteria::CUSTOM); } if ($a) { if ($d) $a->addOr($d); $criteria->addAnd($a); } else if ($d) { $criteria->addAnd($d); } // Add the target node path column. This is used by populateNodes(). $criteria->addSelectColumn($npathR); // Sort by node path to speed up tree construction in populateNodes() $criteria->addAscendingOrderByColumn($npathL); } else { // Add the target node path column. This is used by populateNodes(). $criteria->addSelectColumn(self::NPATH_COLNAME); // Sort by node path to speed up tree construction in populateNodes() $criteria->addAscendingOrderByColumn(self::NPATH_COLNAME); } return $criteria; } /** * This method reconstructs as much of the tree structure as possible from * the given array of objects. Depending on how you execute your query, it * is possible for the ResultSet to contain multiple tree fragments (i.e. * subtrees). The array returned by this method will contain one entry * for each subtree root node it finds. The remaining subtree nodes are * accessible from the getPhpName() ?>Node methods of the * subtree root nodes. * * @param array Array of getPhpName() ?>Node objects * @return array Array of getPhpName() ?>Node objects */ public static function buildTree($nodes) { // Subtree root nodes to return $rootNodes = array(); // Build the tree relations foreach ($nodes as $node) { $sep = strrpos($node->getNodePath(), self::NPATH_SEP); $parentPath = ($sep !== false ? substr($node->getNodePath(), 0, $sep) : ''); $parentNode = null; // Scan other nodes for parent. foreach ($nodes as $pnode) { if ($pnode->getNodePath() == $parentPath) { $parentNode = $pnode; break; } } // If parent was found, attach as child, otherwise its a subtree root if ($parentNode) $parentNode->attachChildNode($node); else $rootNodes[] = $node; } return $rootNodes; } /** * Populates the getPhpName() ?> objects from the * specified ResultSet, wraps them in getPhpName() ?>Node * objects and build the appropriate node relationships. * The array returned by this method will only include the initial targets * of the query, even if ancestors/descendants were also requested. * The ancestors/descendants will be cached in memory and are accessible via * the getNode() methods. * * @param ResultSet * @param Criteria * @return array Array of getPhpName() ?>Node objects. */ public static function populateNodes($rs, $criteria) { $nodes = array(); $targets = array(); $targetfld = count($criteria->getSelectColumns()); getChildrenColumn()) { ?> // set the class once to avoid overhead in the loop $cls = Propel::import(getPhpName() ?>Peer::getOMClass()); // populate the object(s) while($rs->next()) { if (!isset($nodes[$rs->getString(1)])) { getChildrenColumn()) { ?> // class must be set each time from the record row $cls = Propel::import(getPhpName() ?>Peer::getOMClass($rs, 1)); $obj = new $cls(); $obj->hydrate($rs); $nodes[$rs->getString(1)] = new getPhpName() ?>Node($obj); } $node = $nodes[$rs->getString(1)]; if ($node->getNodePath() == $rs->getString($targetfld)) $targets[$node->getNodePath()] = $node; } self::buildTree($nodes); return array_values($targets); } } ?>