![]() |
|
Snippets |
|
Full tree
SELECT n.name, COUNT(*)-1 AS level FROM md_components AS n,md_components AS p WHERE n.tree_left BETWEEN p.tree_left AND p.tree_left GROUP BY n.tree_left ORDER BY n.tree_left;
Tree with further info (level, children counter etc.):
SELECT n.*, round((n.tree_right-n.tree_left-1)/2,0) AS countChildren, count(*)-1+(n.tree_left>1) AS level, ((min(p.tree_right)-n.tree_right-(n.tree_left>1))/2) > 0 AS countPredecessors, (((n.tree_left-max(p.tree_left)>1))) AS countSuccessors FROM md_components n, md_components p WHERE n.tree_left BETWEEN p.tree_left AND p.tree_right AND (p.component_id != n.component_id OR n.tree_left = 1) GROUP BY n.component_id ORDER BY n.tree_left;
Get parent nodes up to root node. Used for breadcrumbs.
SELECT p.*
FROM md_components n, md_components p
WHERE n.tree_left BETWEEN p.tree_left AND p.tree_right
AND n.component_id = 18
ORDER BY n.tree_left;
Getting the first level items of root 1
SELECT
o.*,
COUNT(p.component_id)-1 AS level
FROM md_components AS n,
md_components AS p,
md_components AS o
WHERE o.tree_left BETWEEN p.tree_left AND p.tree_right
AND o.tree_left BETWEEN n.tree_left AND n.tree_right
AND n.component_id = 1
GROUP BY o.tree_left
HAVING level = 1
ORDER BY o.tree_left
user's navigation tree filtered by group permissions using sf_guard plugin:
SELECT mc.* FROM ( md_components AS mc Left Join md_components_has_sf_guard_permission AS cp ON cp.md_components_component_id = mc.component_id Left Join sf_guard_permission AS pm ON pm.id = cp.sf_guard_permission_id Inner Join sf_guard_group_permission AS pg ON pm.id = pg.permission_id Left Join sf_guard_user_group AS ug ON pg.group_id = ug.group_id ), md_components AS cm WHERE mc.tree_left BETWEEN cm.tree_left AND cm.tree_left AND ug.user_id = 1 GROUP BY mc.tree_left ORDER BY mc.tree_left;
user's navigation tree filtered by group permissions and additional user permissions using sf_guard plugin:
SELECT mc.* FROM ( md_components AS mc Left Join md_components_has_sf_guard_permission AS cp ON cp.md_components_component_id = mc.component_id Left Join sf_guard_permission AS pm ON pm.id = cp.sf_guard_permission_id Inner Join sf_guard_group_permission AS pg ON pm.id = pg.permission_id Left Join sf_guard_user_group AS ug ON pg.group_id = ug.group_id Left Join sf_guard_user_permission AS um ON pm.id = um.permission_id ), md_components AS cm WHERE mc.tree_left BETWEEN cm.tree_left AND cm.tree_left AND (ug.user_id = 1 AND um.user_id=1) GROUP BY mc.tree_left ORDER BY mc.tree_left;
Look at module action class for further information.
/apps/backend/modules/navigation/templates/_list_td_tabular.php // delete action for node enabled if it has parent <?php if($navigation->getParent()>0): ?> <?php echo link_to(__('delete'), 'navigation/delete?component_id='.$navigation->getComponentId(), array ('post' => true,'confirm' => __('Are you sure?'),));?> <?php endif; ?> // edit node <?php echo link_to(__('edit'), 'navigation/edit?component_id='.$navigation->getComponentId());?> // tree actions if node level greater zero <?php if($navigation->hasChilds()>0 && $navigation->isLevel() > 0): ?> // perform tree delete action <?php echo link_to(__('delete tree'), 'navigation/deleteDescendants?component_id='.$navigation->getComponentId(), array ('post' => true,'confirm' => __('Are you sure?')));?> <?php if($navigation->hasChilds() > 0):?> // allow tree copy action if node has children <?php echo link_to(__('copy tree'), 'navigation/copyDescendants?component_id='.$navigation->getComponentId().'&root_id='.$navigation->selfRoot(), array ('post' => true,'confirm' => __('Are you sure?')));?> <?php endif; ?> <?php endif; ?> // move operations <?php if($navigation->isLevel() > 0): ?> <?php // if a node's root has a successor then move to previous root if($navigation->nextRoot()){ echo link_to(__('moveRootPrev'), 'navigation/moveRootPrev?component_id='. $navigation->getComponentId().'&root_id='.$navigation->selfRoot(), array('class' => 'moveRootPrev')); } // if a node's root has a predecessor then move to next root if($navigation->prevRoot()){ echo link_to(__('moveRootNext'), 'navigation/moveRootNext?component_id='.$navigation->getComponentId().'&root_id='.$navigation->selfRoot(), array('class' => 'moveRootNext')); } ?> <?php endif; ?> // self-explaining <?php echo link_to(__('insertAsFirstChildOf'), 'navigation/insertAsFirstChildOf?component_id='. $navigation->getComponentId(), array('class' => 'insertAsFirstChildOf'));?> <?php echo link_to(__('insertAsLastChildOf'), 'navigation/insertAsLastChildOf?component_id='.$navigation->getComponentId(), array('class' => 'insertAsLastChildOf'));?> if($navigation->isLevel() > 0){ echo link_to(__('insertAsPrevSiblingOf'), 'navigation/insertAsPrevSiblingOf?component_id='.$navigation->getComponentId(), array('class' => 'insertAsPrevSiblingOf')); echo link_to(__('insertAsNextSiblingOf'), 'navigation/insertAsNextSiblingOf?component_id='.$navigation->getComponentId(), array('class' => 'insertAsNextSiblingOf')); } ?> <?php if($navigation->getParent()>0): ?> // move to parent node and place before if($navigation->isLevel()>1){ echo link_to(__('moveLeftUp'), 'navigation/moveLeftUp?component_id='. $navigation->getComponentId(), array('class' => 'moveLeftUp')); } // move to parent node and place after if($navigation->isLevel()>1){ echo link_to(__('moveLeftDown'), 'navigation/moveLeftDown?component_id='.$navigation->getComponentId(), array('class' => 'moveLeftDown')); } // place as predecessor's child if ( $navigation->isLevel() > 0 && $navigation->prevSibling() ) { echo link_to(__('moveRightPrev'), 'navigation/moveRightPrev?component_id='.$navigation->getComponentId(), array('class' => 'moveRightPrev')); } // place as successor's child if ( $navigation->isLevel() > 0 && $navigation->nextSibling() ){ echo link_to(__('moveRightNext'), 'navigation/moveRightNext?component_id='.$navigation->getComponentId(), array('class' => 'moveRightNext')); } ?> if($navigation->isLevel()>0){ if($navigation->prevSibling()){ echo link_to(__('moveToPrevSiblingOf'), 'navigation/moveToPrevSiblingOf?component_id='.$navigation->getComponentId(),array('class' => 'moveUp')); } if($navigation->nextSibling()){ echo link_to(__('moveToNextSiblingOf'), 'navigation/moveToNextSiblingOf?component_id='.$navigation->getComponentId(), array('class' => 'moveDown')); } } ?>
Enjoy it.
/apps/backend/modules/navigation/actions/actions.class.php
<?php /** * navigation actions. */ class navigationActions extends autonavigationActions { public function executeList() { $this->typeOfList = 1; switch($this->typeOfList) { case 1: $pager = new Navigation(); $this->pager = $pager->getTree(0,200); break; default: $this->processSort(); $this->processFilters(); // pager $navigation = new Navigation(); $this->pager = new sfPropelPager('Navigation', 100); $c = new Criteria(); $c->addAscendingOrderByColumn(NavigationPeer::TREE_LEFT); if($this->getUser()->hasCredential('SHOW_ALL_NAVIGATION_ROOTS')){ } else { $rootNodes = $navigation->getRootNodes(); $conditions = array(); foreach($rootNodes as $credentialName => $credential) { if($this->getUser()->hasCredential($credentialName)){ $c1 = $c->getNewCriterion(NavigationPeer::TREE_LEFT, $credential["left"], Criteria::GREATER_THAN); $c2 = $c->getNewCriterion(NavigationPeer::TREE_RIGHT, $credential["right"], Criteria::LESS_THAN); $conditions[] = $c1->addAnd($c2); } } if(count($conditions) > 1) { foreach($conditions as $condition){ $c->addOr($condition); } } else { $c->add($conditions[0]); } } $this->addSortCriteria($c); $this->addFiltersCriteria($c); $this->pager->setCriteria($c); $this->pager->setPage($this->getRequestParameter('page', 1)); $this->pager->init(); break; } } public function executeShow() { $this->component = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $this->paths = $this->component->getPath(); } public function executeBlockable() { $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $state = $this->getRequestParameter('state')==1 ? 1 : 0; $navigation->setIsBlocked($state); $navigation->save(); $this->state = $state; $this->navigation = $navigation; } public function executeNavigatable() { $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $state = $this->getRequestParameter('state')==1 ? 1 : 0; $navigation->setIsNavigation($state); $navigation->save(); $this->state = $state; $this->navigation = $navigation; } private function getPrimaryRoot(){ return NavigationPeer::retrieveByPk(1); } // Default Root Node public function executeMakeRoot(){ $root = new Navigation(); $root->makeRoot(); $root->save(); return $this->redirect('navigation/edit?component_id='. $root->getNavigationId()); } // Further Root Node public function executeMakeNextRoot(){ $root = new Navigation(); $root->makeNextRoot(); $root->save(); return $this->redirect('navigation/edit?component_id='. $root->getNavigationId()); } // Delete Branch public function executeDeleteDescendants(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $navigation->deleteDescendants(); $navigation = $navigation->reload(); $navigation->delete(); return $this->redirect('navigation/list'); } // insert first child node public function executeInsertAsFirstChildOf(){ $this->message = "Nun wird ein Kindelement erzeugt"; $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $child = new Navigation(); $child->insertAsFirstChildOf($navigation); $child->save(); return $this->redirect('navigation/edit?component_id='. $child->getNavigationId()); } // insert last child node public function executeInsertAsLastChildOf(){ $this->message = "Nun wird ein Kindelement erzeugt"; $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $child = new Navigation(); $child->insertAsLastChildOf($navigation); $child->save(); return $this->redirect('navigation/edit?component_id='. $child->getNavigationId()); } // insert sibling before public function executeInsertAsNextSiblingOf(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $child = new Navigation(); $child->insertAsNextSiblingOf($navigation); $child->save(); return $this->redirect('navigation/edit?component_id='. $child->getNavigationId()); } // insert sibling after public function executeInsertAsPrevSiblingOf(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $child = new Navigation(); $child->insertAsPrevSiblingOf($navigation); $child->save(); return $this->redirect('navigation/edit?component_id='. $child->getNavigationId()); } /*Tree Modification*/ // UP public function executeMoveToPrevSiblingOf(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $siblingNavigation = $navigation->retrievePrevSibling($navigation); $navigation->moveToPrevSiblingOf($siblingNavigation); $navigation->save(); return $this->redirect('navigation/list'); } //DOWN public function executeMoveToNextSiblingOf(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $siblingNavigation = $navigation->retrieveNextSibling($navigation); $navigation->moveToNextSiblingOf($siblingNavigation); $navigation->save(); return $this->redirect('navigation/list'); } // LEFT UP public function executeMoveLeftUp(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $parentNavigation = NavigationPeer::retrieveByPk($navigation->getParent()); $navigation->moveToPrevSiblingOf($parentNavigation); $navigation->save(); return $this->redirect('navigation/list'); } // LEFT DOWN public function executeMoveLeftDown(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $parentNavigation = NavigationPeer::retrieveByPk($navigation->getParent()); $navigation->moveToNextSiblingOf($parentNavigation); $navigation->save(); return $this->redirect('navigation/list'); } // RIGHT FIRST public function executeMoveRightPrev(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $prevSibling = $navigation->retrievePrevSibling($navigation); $navigation->moveToLastChildOf($prevSibling); $navigation->save(); return $this->redirect('navigation/list'); } // RIGHT LAST public function executeMoveRightNext(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $nextSibling = $navigation->retrieveNextSibling($navigation); $navigation->moveToLastChildOf($nextSibling); $navigation->save(); return $this->redirect('navigation/list'); } // ROOT PREV public function executeMoveRootPrev(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $rootNavigation = NavigationPeer::retrieveByPk($this->getRequestParameter('root_id')); $prevRootNavigation = $rootNavigation->retrievePrevSibling($rootNavigation); $navigation->moveToLastChildOf($prevRootNavigation); $navigation->save(); return $this->redirect('navigation/list'); } // ROOT NEXT public function executeMoveRootNext(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $rootNavigation = NavigationPeer::retrieveByPk($this->getRequestParameter('root_id')); $nextRootNavigation = $rootNavigation->retrieveNextSibling($rootNavigation); $navigation->moveToLastChildOf($nextRootNavigation); $navigation->save(); return $this->redirect('navigation/list'); } // Duplicate Tree public function executeCopyDescendants(){ $navigation = NavigationPeer::retrieveByPk($this->getRequestParameter('component_id')); $parentNavigation = NavigationPeer::retrieveByPk($navigation->getParent()); $newParentNavigation = $this->copyNode($navigation, $parentNavigation); $this->iterateOnDescendants($navigation->getDescendants() , $newParentNavigation); return $this->redirect('navigation/list'); } private function iterateOnDescendants($navigations, $prevNavigation){ foreach($navigations as $navigation){ $actualNavigation = $this->copyNodeDescendants($navigation, $prevNavigation); $prevNavigation = $actualNavigation; } } private function transferData(Navigation $navigation){ $newNavigation = new Navigation(); $newNavigation->setName($navigation->getName()); $newNavigation->setAction($navigation->getAction()); $newNavigation->setParameter($navigation->getParameter()); $newNavigation->setCaption($navigation->getCaption()); $newNavigation->setDescription($navigation->getDescription()); $newNavigation->setIsNavigation(0); $newNavigation->setIsBlocked(0); $newNavigation->setIsTemplate(0); return $newNavigation; } private function copyNodeDescendants($navigation, $prevNavigation){ $newNavigation = $this->transferData($navigation); if($navigation->getLevel() == $prevNavigation->getLevel() ){ $newNavigation->insertAsNextSiblingOf($prevNavigation); } elseif($navigation->getLevel() > $prevNavigation->getLevel()){ $newNavigation->insertAsLastChildOf($prevNavigation); } else { $parentNavigation = NavigationPeer::retrieveByPk($prevNavigation->getParent()); $newNavigation->insertAsNextSiblingOf($parentNavigation); } $newNavigation->save(); return $newNavigation->reload(); } private function copyNode($navigation, $parentNavigation){ $newNavigation = $this->transferData($navigation); $newNavigation->insertAsLastChildOf($parentNavigation); $newNavigation->save(); return $newNavigation->reload(); } }
(This module is for administering big nested navigation trees, not for being used in a high performance web site. If you want to build a resultset for navigations then setup a custom query. There are enough examples out there for querying a nested set )
NavigationModel Scheme
<table name="md_components" phpName="Navigation"> <column name="component_id" type="INTEGER" size="11" primaryKey="true" required="true" autoIncrement="true"/> <column name="name" type="VARCHAR" size="50" required="true" phpName="Name"/> <column name="action" type="VARCHAR" size="50" phpName="Action"/> <column name="caption" type="VARCHAR" size="50" phpName="Caption"/> <column name="description" type="LONGVARCHAR" phpName="Description"/> <column name="parameter" type="VARCHAR" size="50" phpName="Parameter"/> <column name="image" type="VARCHAR" size="50" phpName="Image"/> <column name="tree_left" type="INTEGER" size="11" phpName="Left"/> <column name="tree_right" type="INTEGER" size="11" phpName="Right"/> <column name="tree_parent" type="INTEGER" size="11" default="0" phpName="Parent"/> <column name="tree_scope" type="INTEGER" size="11" default="0" phpName="Scope"/> <column name="created_at" type="TIMESTAMP" required="true" phpName="CreationDate"/> <column name="created_by" type="INTEGER" size="11" default="1" phpName="Creator"/> <column name="templatable" type="BOOLEAN" phpName="IsTemplate"/> <column name="blockable" type="BOOLEAN" phpName="IsBlocked"/> <column name="navigatable" type="BOOLEAN" phpName="IsNavigation"/> <column name="deleted_at" type="TIMESTAMP"/> <column name="deleted_by" type="INTEGER" size="11"/> <foreign-key foreignTable="sf_guard_user" name="creator" onDelete="setnull"> <reference local="created_by" foreign="id"/> </foreign-key> <foreign-key foreignTable="sf_guard_user" name="FK_USER" onDelete="setnull"> <reference local="deleted_by" foreign="id"/> </foreign-key> </table>
<?php /** * Subclass for representing a row from the 'md_components' table. * * * * @package lib.model */ class Navigation extends BaseNavigation { public function makeNextRoot() { $max = $this->getMaxRight(); $this->setLeftValue($max + 1); $this->setRightValue($max + 2); } public function getNavigationId(){ return $this->getComponentId(); } public function getMaxRight(){ $connection = Propel::getConnection(); $query = 'SELECT MAX(%s) AS max FROM %s'; $query = sprintf($query, NavigationPeer::TREE_RIGHT, NavigationPeer::TABLE_NAME); $statement = $connection->prepareStatement($query); $resultset = $statement->executeQuery(); $resultset->next(); return $resultset->getInt('max'); } public function getMaxLeft(){ $connection = Propel::getConnection(); $query = 'SELECT MAX(%s) AS max FROM %s'; $query = sprintf($query, NavigationPeer::TREE_LEFT, NavigationPeer::TABLE_NAME); $statement = $connection->prepareStatement($query); $resultset = $statement->executeQuery(); $resultset->next(); return $resultset->getInt('max'); } public function getRootNodes(){ $connection = Propel::getConnection(); $query = 'SELECT * FROM %s WHERE %s %s %s;'; $query = sprintf($query, NavigationPeer::TABLE_NAME, NavigationPeer::TREE_PARENT, Criteria::EQUAL, 0); $statement = $connection->prepareStatement($query); $resultset = $statement->executeQuery(); $credential = array(); foreach($resultset as $result){ $credential[$result["name"]]["component_id"] = $result["component_id"]; $credential[$result["name"]]["name"] = $result["name"]; $credential[$result["name"]]["left"] = $result["tree_left"]; $credential[$result["name"]]["right"] = $result["tree_right"]; } return $credential; } public function getTree($offset = 0, $limit = 10, $options = null){ $query = ' SELECT *, ( SELECT CONCAT(COUNT(*)) FROM md_components MA WHERE ( ( MA.TREE_LEFT < MM.TREE_LEFT AND MA.TREE_RIGHT > MM.TREE_RIGHT ) AND MA.TREE_SCOPE = MM.TREE_SCOPE ) ) AS isLevel, ( SELECT MZ4.COMPONENT_ID FROM md_components MZ4 , md_components MZ5 WHERE MZ5.TREE_LEFT BETWEEN MZ4.TREE_LEFT AND MZ4.TREE_RIGHT AND MZ5.COMPONENT_ID = MM.COMPONENT_ID ORDER BY MZ4.TREE_LEFT LIMIT 1,1 ) AS selfFirstLevel, ( SELECT IF( MB.TREE_RIGHT - MB.TREE_LEFT > 1, 1, 0) FROM md_components MB WHERE MB.COMPONENT_ID = MM.COMPONENT_ID AND MB.TREE_SCOPE = MM.TREE_SCOPE ) AS hasChilds, ( SELECT MC.COMPONENT_ID FROM md_components MC WHERE (MM.TREE_LEFT = MC.TREE_RIGHT + 1) AND MC.TREE_SCOPE = MM.TREE_SCOPE ) AS prevSibling, ( SELECT MD.COMPONENT_ID FROM md_components MD WHERE (MM.TREE_RIGHT = MD.TREE_LEFT - 1) AND MD.TREE_SCOPE = MM.TREE_SCOPE ) AS nextSibling, ( SELECT IF ( ( SELECT IF ( MQ.TREE_RIGHT - MQ.TREE_LEFT > 1, 1, 0 ) FROM md_components MQ WHERE MQ.COMPONENT_ID = MM.COMPONENT_ID AND MQ.TREE_SCOPE = MM.TREE_SCOPE ) = 1 , ME.COMPONENT_ID, NULL ) FROM md_components ME WHERE ME.TREE_LEFT = MM.TREE_LEFT + 1 AND ME.TREE_SCOPE = MM.TREE_SCOPE ) AS firstChild, ( SELECT IF ( ( SELECT IF( MS.TREE_RIGHT - MS.TREE_LEFT > 1, 1, 0 ) FROM md_components MS WHERE MS.COMPONENT_ID = MM.COMPONENT_ID AND MS.TREE_SCOPE = MM.TREE_SCOPE ) = 1 , MF.COMPONENT_ID, NULL ) FROM md_components MF WHERE MF.TREE_RIGHT = MM.TREE_RIGHT - 1 AND MF.TREE_SCOPE = MM.TREE_SCOPE ) AS lastChild, ( SELECT MX.COMPONENT_ID FROM md_components MX WHERE MX.TREE_LEFT - 1 = ( SELECT MZ.TREE_RIGHT FROM md_components MZ WHERE (MZ.TREE_RIGHT > MM.TREE_RIGHT) AND (MZ.TREE_LEFT < MM.TREE_LEFT) AND (MZ.TREE_PARENT = 0) AND MZ.TREE_SCOPE = MM.TREE_SCOPE ) ) AS nextRoot, ( SELECT MX.COMPONENT_ID FROM md_components MX WHERE MX.TREE_RIGHT + 1 = ( SELECT MZ2.TREE_LEFT FROM md_components MZ2 WHERE (MZ2.TREE_RIGHT > MM.TREE_RIGHT) AND (MZ2.TREE_LEFT < MM.TREE_LEFT) AND (MZ2.TREE_PARENT = 0) AND MZ2.TREE_SCOPE = MM.TREE_SCOPE ) ) AS prevRoot, ( SELECT MZ3.COMPONENT_ID FROM md_components MZ3 WHERE (MZ3.TREE_RIGHT > MM.TREE_RIGHT) AND (MZ3.TREE_LEFT < MM.TREE_LEFT) AND (MZ3.TREE_PARENT = 0) AND MZ3.TREE_SCOPE = MM.TREE_SCOPE ) AS selfRoot FROM md_components MM '; $query .= ' ORDER BY MM.TREE_LEFT ASC '; $query .= 'LIMIT '. $offset . ', ' . $limit; $connection = Propel::getConnection(); $statement = $connection->createStatement( ); $result = $statement->executeQuery( $query , ResultSet::FETCHMODE_NUM); $objects = NavigationPeer::populateObjects( $result ); $phpNames = NavigationPeer::getFieldNames(BasePeer::TYPE_PHPNAME); $additionalColumns = array_merge( $phpNames, array("isLevel", "selfFirstLevel", "hasChilds", "prevSibling", "nextSibling", "firstChild", "lastChild", "prevRoot", "nextRoot", "selfRoot") ); foreach($result as $key => $object){ foreach($object as $column => $value){ if($column > count($phpNames)-1){ $method = $additionalColumns[$column]; $objects[$key-1]->$method = $value; } } } return $objects; } /*no setter functions*/ public function lastChild(){ return $this->lastChild; } public function selfFirstLevel(){ return $this->selfFirstLevel; } public function firstChild(){ return $this->firstChild; } public function prevRoot(){ return $this->prevRoot; } public function nextRoot(){ return $this->nextRoot; } public function selfRoot(){ return $this->selfRoot; } public function nextSibling(){ return $this->nextSibling; } public function prevSibling(){ return $this->prevSibling; } public function isLevel(){ return $this->isLevel; } public function hasChilds(){ return $this->hasChilds; } } $columns_map = array ( 'left' => NavigationPeer::TREE_LEFT, 'right' => NavigationPeer::TREE_RIGHT, 'parent' => NavigationPeer::TREE_PARENT, 'scope' => NavigationPeer::TREE_SCOPE ); sfPropelBehavior::add('Navigation', array('actasnestedset' => array('columns' => $columns_map)));
NavigationModel Scheme
<table name="md_components" phpName="Navigation"> <column name="component_id" type="INTEGER" size="11" primaryKey="true" required="true" autoIncrement="true"/> <column name="name" type="VARCHAR" size="50" required="true" phpName="Name"/> <column name="action" type="VARCHAR" size="50" phpName="Action"/> <column name="caption" type="VARCHAR" size="50" phpName="Caption"/> <column name="description" type="LONGVARCHAR" phpName="Description"/> <column name="parameter" type="VARCHAR" size="50" phpName="Parameter"/> <column name="image" type="VARCHAR" size="50" phpName="Image"/> <column name="tree_left" type="INTEGER" size="11" phpName="Left"/> <column name="tree_right" type="INTEGER" size="11" phpName="Right"/> <column name="tree_parent" type="INTEGER" size="11" default="0" phpName="Parent"/> <column name="tree_scope" type="INTEGER" size="11" default="0" phpName="Scope"/> <column name="created_at" type="TIMESTAMP" required="true" phpName="CreationDate"/> <column name="created_by" type="INTEGER" size="11" default="1" phpName="Creator"/> <column name="templatable" type="BOOLEAN" phpName="IsTemplate"/> <column name="blockable" type="BOOLEAN" phpName="IsBlocked"/> <column name="navigatable" type="BOOLEAN" phpName="IsNavigation"/> <column name="deleted_at" type="TIMESTAMP"/> <column name="deleted_by" type="INTEGER" size="11"/> <foreign-key foreignTable="sf_guard_user" name="creator" onDelete="setnull"> <reference local="created_by" foreign="id"/> </foreign-key> <foreign-key foreignTable="sf_guard_user" name="FK_USER" onDelete="setnull"> <reference local="deleted_by" foreign="id"/> </foreign-key> </table>
<?php /** * Subclass for representing a row from the 'md_components' table. * * * * @package lib.model */ class Navigation extends BaseNavigation { public function makeNextRoot() { $max = $this->getMaxRight(); $this->setLeftValue($max + 1); $this->setRightValue($max + 2); } public function getNavigationId(){ return $this->getComponentId(); } public function getMaxRight(){ $connection = Propel::getConnection(); $query = 'SELECT MAX(%s) AS max FROM %s'; $query = sprintf($query, NavigationPeer::TREE_RIGHT, NavigationPeer::TABLE_NAME); $statement = $connection->prepareStatement($query); $resultset = $statement->executeQuery(); $resultset->next(); return $resultset->getInt('max'); } public function getMaxLeft(){ $connection = Propel::getConnection(); $query = 'SELECT MAX(%s) AS max FROM %s'; $query = sprintf($query, NavigationPeer::TREE_LEFT, NavigationPeer::TABLE_NAME); $statement = $connection->prepareStatement($query); $resultset = $statement->executeQuery(); $resultset->next(); return $resultset->getInt('max'); } public function getRootNodes(){ $connection = Propel::getConnection(); $query = 'SELECT * FROM %s WHERE %s %s %s;'; $query = sprintf($query, NavigationPeer::TABLE_NAME, NavigationPeer::TREE_PARENT, Criteria::EQUAL, 0); $statement = $connection->prepareStatement($query); $resultset = $statement->executeQuery(); $credential = array(); foreach($resultset as $result){ $credential[$result["name"]]["component_id"] = $result["component_id"]; $credential[$result["name"]]["name"] = $result["name"]; $credential[$result["name"]]["left"] = $result["tree_left"]; $credential[$result["name"]]["right"] = $result["tree_right"]; } return $credential; } public function getTree($offset = 0, $limit = 10, $options = null){ $query = ' SELECT *, ( SELECT CONCAT(COUNT(*)) FROM md_components MA WHERE ( ( MA.TREE_LEFT < MM.TREE_LEFT AND MA.TREE_RIGHT > MM.TREE_RIGHT ) AND MA.TREE_SCOPE = MM.TREE_SCOPE ) ) AS isLevel, ( SELECT MZ4.COMPONENT_ID FROM md_components MZ4 , md_components MZ5 WHERE MZ5.TREE_LEFT BETWEEN MZ4.TREE_LEFT AND MZ4.TREE_RIGHT AND MZ5.COMPONENT_ID = MM.COMPONENT_ID ORDER BY MZ4.TREE_LEFT LIMIT 1,1 ) AS selfFirstLevel, ( SELECT IF( MB.TREE_RIGHT - MB.TREE_LEFT > 1, 1, 0) FROM md_components MB WHERE MB.COMPONENT_ID = MM.COMPONENT_ID AND MB.TREE_SCOPE = MM.TREE_SCOPE ) AS hasChilds, ( SELECT MC.COMPONENT_ID FROM md_components MC WHERE (MM.TREE_LEFT = MC.TREE_RIGHT + 1) AND MC.TREE_SCOPE = MM.TREE_SCOPE ) AS prevSibling, ( SELECT MD.COMPONENT_ID FROM md_components MD WHERE (MM.TREE_RIGHT = MD.TREE_LEFT - 1) AND MD.TREE_SCOPE = MM.TREE_SCOPE ) AS nextSibling, ( SELECT IF ( ( SELECT IF ( MQ.TREE_RIGHT - MQ.TREE_LEFT > 1, 1, 0 ) FROM md_components MQ WHERE MQ.COMPONENT_ID = MM.COMPONENT_ID AND MQ.TREE_SCOPE = MM.TREE_SCOPE ) = 1 , ME.COMPONENT_ID, NULL ) FROM md_components ME WHERE ME.TREE_LEFT = MM.TREE_LEFT + 1 AND ME.TREE_SCOPE = MM.TREE_SCOPE ) AS firstChild, ( SELECT IF ( ( SELECT IF( MS.TREE_RIGHT - MS.TREE_LEFT > 1, 1, 0 ) FROM md_components MS WHERE MS.COMPONENT_ID = MM.COMPONENT_ID AND MS.TREE_SCOPE = MM.TREE_SCOPE ) = 1 , MF.COMPONENT_ID, NULL ) FROM md_components MF WHERE MF.TREE_RIGHT = MM.TREE_RIGHT - 1 AND MF.TREE_SCOPE = MM.TREE_SCOPE ) AS lastChild, ( SELECT MX.COMPONENT_ID FROM md_components MX WHERE MX.TREE_LEFT - 1 = ( SELECT MZ.TREE_RIGHT FROM md_components MZ WHERE (MZ.TREE_RIGHT > MM.TREE_RIGHT) AND (MZ.TREE_LEFT < MM.TREE_LEFT) AND (MZ.TREE_PARENT = 0) AND MZ.TREE_SCOPE = MM.TREE_SCOPE ) ) AS nextRoot, ( SELECT MX.COMPONENT_ID FROM md_components MX WHERE MX.TREE_RIGHT + 1 = ( SELECT MZ2.TREE_LEFT FROM md_components MZ2 WHERE (MZ2.TREE_RIGHT > MM.TREE_RIGHT) AND (MZ2.TREE_LEFT < MM.TREE_LEFT) AND (MZ2.TREE_PARENT = 0) AND MZ2.TREE_SCOPE = MM.TREE_SCOPE ) ) AS prevRoot, ( SELECT MZ3.COMPONENT_ID FROM md_components MZ3 WHERE (MZ3.TREE_RIGHT > MM.TREE_RIGHT) AND (MZ3.TREE_LEFT < MM.TREE_LEFT) AND (MZ3.TREE_PARENT = 0) AND MZ3.TREE_SCOPE = MM.TREE_SCOPE ) AS selfRoot FROM md_components MM '; $query .= ' ORDER BY MM.TREE_LEFT ASC '; $query .= 'LIMIT '. $offset . ', ' . $limit; $connection = Propel::getConnection(); $statement = $connection->createStatement( ); $result = $statement->executeQuery( $query , ResultSet::FETCHMODE_NUM); $objects = NavigationPeer::populateObjects( $result ); $phpNames = NavigationPeer::getFieldNames(BasePeer::TYPE_PHPNAME); $additionalColumns = array_merge( $phpNames, array("isLevel", "selfFirstLevel", "hasChilds", "prevSibling", "nextSibling", "firstChild", "lastChild", "prevRoot", "nextRoot", "selfRoot") ); foreach($result as $key => $object){ foreach($object as $column => $value){ if($column > 15){ $method = $additionalColumns[$column]; $objects[$key-1]->$method = $value; } } } return $objects; } /*no setter functions*/ public function lastChild(){ return $this->lastChild; } public function selfFirstLevel(){ return $this->selfFirstLevel; } public function firstChild(){ return $this->firstChild; } public function prevRoot(){ return $this->prevRoot; } public function nextRoot(){ return $this->nextRoot; } public function selfRoot(){ return $this->selfRoot; } public function nextSibling(){ return $this->nextSibling; } public function prevSibling(){ return $this->prevSibling; } public function isLevel(){ return $this->isLevel; } public function hasChilds(){ return $this->hasChilds; } } $columns_map = array ( 'left' => NavigationPeer::TREE_LEFT, 'right' => NavigationPeer::TREE_RIGHT, 'parent' => NavigationPeer::TREE_PARENT, 'scope' => NavigationPeer::TREE_SCOPE ); sfPr