Apache Zeta Components Manual :: File Source for db_parent_child.php

Source for file db_parent_child.php

Documentation is available at db_parent_child.php

  1. <?php
  2. /**
  3.  * File containing the ezcTreeDbParentChild class.
  4.  *
  5.  * Licensed to the Apache Software Foundation (ASF) under one
  6.  * or more contributor license agreements.  See the NOTICE file
  7.  * distributed with this work for additional information
  8.  * regarding copyright ownership.  The ASF licenses this file
  9.  * to you under the Apache License, Version 2.0 (the
  10.  * "License"); you may not use this file except in compliance
  11.  * with the License.  You may obtain a copy of the License at
  12.  * 
  13.  *   http://www.apache.org/licenses/LICENSE-2.0
  14.  * 
  15.  * Unless required by applicable law or agreed to in writing,
  16.  * software distributed under the License is distributed on an
  17.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18.  * KIND, either express or implied.  See the License for the
  19.  * specific language governing permissions and limitations
  20.  * under the License.
  21.  *
  22.  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  23.  * @version //autogentag//
  24.  * @filesource
  25.  * @package TreeDatabaseTiein
  26.  */
  27.  
  28. /**
  29.  * ezcTreeDbParentChild implements a tree backend which stores parent/child
  30.  * information in a simple table containing the node's ID and its parent's ID.
  31.  *
  32.  * The table that stores the index (configured using the $indexTableName argument
  33.  * of the {@link __construct} method) should contain at least two fields. The
  34.  * first one 'id' will contain the node's ID, the second one 'parent_id' the ID
  35.  * of the node's parent. Both fields should be of the same database field type.
  36.  * Supported field types are either integer or a string type.
  37.  * In order to use auto-generated IDs, the 'id' field needs to be an
  38.  * auto-incrementing integer field, by using either an auto-increment field, or
  39.  * a sequence.
  40.  *
  41.  * @property-read ezcTreeDbDataStore $store 
  42.  *                 The data store that is used for retrieving/storing data.
  43.  * @property      string $nodeClassName 
  44.  *                 Which class is used as tree node - this class *must* inherit
  45.  *                 the ezcTreeNode class.
  46.  *
  47.  * @package TreeDatabaseTiein
  48.  * @version //autogentag//
  49.  * @mainclass
  50.  */
  51. {
  52.     /**
  53.      * Creates a new ezcTreeDbParentChild object.
  54.      *
  55.      * The different arguments to the method configure which database
  56.      * connection ($dbh) is used to access the database and the $indexTableName
  57.      * argument which table is used to retrieve the relation data from. The
  58.      * $store argument configure which data store is used with this tree.
  59.      *
  60.      * It is up to the user to create the database table and make sure it is
  61.      * empty.
  62.      * 
  63.      * @param ezcDbHandler       $dbh 
  64.      * @param string             $indexTableName 
  65.      * @param ezcTreeDbDataStore $store 
  66.      */
  67.     public static function createezcDbHandler $dbh$indexTableNameezcTreeDbDataStore $store )
  68.     {
  69.         return new ezcTreeDbParentChild$dbh$indexTableName$store );
  70.     }
  71.  
  72.     /**
  73.      * Runs SQL to get all the children of the node with ID $nodeId as a PDO
  74.      * result set.
  75.      *
  76.      * @param string $nodeId 
  77.      * @return PDOStatement 
  78.      */
  79.     protected function fetchChildRecords$nodeId )
  80.     {
  81.         $db $this->dbh;
  82.         $q $db->createSelectQuery();
  83.  
  84.         // SELECT id, parent_id
  85.         // FROM indexTable
  86.         // WHERE parent_id = $nodeId
  87.         $q->select'id, parent_id' )
  88.           ->from$db->quoteIdentifier$this->indexTableName ) )
  89.           ->where$q->expr->eq'parent_id'$q->bindValue$nodeId ) ) );
  90.  
  91.         $s $q->prepare();
  92.         $s->execute();
  93.         return $s;
  94.     }
  95.  
  96.     /**
  97.      * Adds the children nodes of the node with ID $nodeId to the
  98.      * ezcTreeNodeList $list.
  99.      *
  100.      * @param ezcTreeNodeList $list 
  101.      * @param string          $nodeId 
  102.      */
  103.     private function addChildNodesDepthFirstezcTreeNodeList $list$nodeId )
  104.     {
  105.         $className $this->properties['nodeClassName'];
  106.         foreach $this->fetchChildRecords$nodeId as $record )
  107.         {
  108.             $list->addNodenew $className$this$record['id') );
  109.             $this->addChildNodesDepthFirst$list$record['id');
  110.         }
  111.     }
  112.  
  113.     /**
  114.      * Returns all the children of the node with ID $nodeId.
  115.      *
  116.      * @param string $nodeId 
  117.      * @return ezcTreeNodeList 
  118.      */
  119.     public function fetchChildren$nodeId )
  120.     {
  121.         $className $this->properties['nodeClassName'];
  122.         $list new ezcTreeNodeList;
  123.         foreach $this->fetchChildRecords$nodeId as $record )
  124.         {
  125.             $list->addNodenew $className$this$record['id') );
  126.         }
  127.         return $list;
  128.     }
  129.  
  130.     /**
  131.      * Returns all the nodes in the path from the root node to the node with ID
  132.      * $nodeId, including those two nodes.
  133.      *
  134.      * @param string $nodeId 
  135.      * @return ezcTreeNodeList 
  136.      */
  137.     public function fetchPath$nodeId )
  138.     {
  139.         $className $this->properties['nodeClassName'];
  140.  
  141.         $nodes array();
  142.         $nodes[new $className$this$nodeId );
  143.  
  144.         $nodeId $this->getParentId$nodeId );
  145.  
  146.         while $nodeId != null )
  147.         {
  148.             $nodes[new $className$this$nodeId );
  149.             $nodeId $this->getParentId$nodeId );
  150.         }
  151.  
  152.         $list new ezcTreeNodeList;
  153.         foreach array_reverse$nodes as $node )
  154.         {
  155.             $list->addNode$node );
  156.         }
  157.         return $list;
  158.     }
  159.  
  160.     /**
  161.      * Returns the node with ID $nodeId and all its children, sorted according to
  162.      * the {@link http://en.wikipedia.org/wiki/Depth-first_search Depth-first sorting}
  163.      * algorithm.
  164.      *
  165.      * @param string $nodeId 
  166.      * @return ezcTreeNodeList 
  167.      */
  168.     public function fetchSubtreeDepthFirst$nodeId )
  169.     {
  170.         $className $this->properties['nodeClassName'];
  171.         $list new ezcTreeNodeList;
  172.         $list->addNodenew $className$this$nodeId ) );
  173.         $this->addChildNodesDepthFirst$list$nodeId );
  174.         return $list;
  175.     }
  176.  
  177.     /**
  178.      * Alias for fetchSubtreeDepthFirst().
  179.      *
  180.      * @param string $nodeId 
  181.      * @return ezcTreeNodeList 
  182.      */
  183.     public function fetchSubtree$nodeId )
  184.     {
  185.         return $this->fetchSubtreeDepthFirst$nodeId );
  186.     }
  187.  
  188.     /**
  189.      * Adds the children nodes of the node with ID $nodeId to the
  190.      * ezcTreeNodeList $list.
  191.      *
  192.      * @param ezcTreeNodeList $list 
  193.      * @param string          $nodeId 
  194.      */
  195.     protected function addChildNodesBreadthFirstezcTreeNodeList $list$nodeId )
  196.     {
  197.         $className $this->properties['nodeClassName'];
  198.         $childRecords $this->fetchChildRecords$nodeId )->fetchAll();
  199.         foreach $childRecords as $record )
  200.         {
  201.             $list->addNodenew $className$this$record['id') );
  202.         }
  203.         foreach $childRecords as $record )
  204.         {
  205.             $this->addChildNodesBreadthFirst$list$record['id');
  206.         }
  207.     }
  208.  
  209.     /**
  210.      * Returns the node with ID $nodeId and all its children, sorted according to
  211.      * the {@link http://en.wikipedia.org/wiki/Breadth-first_search Breadth-first sorting}
  212.      * algorithm.
  213.      *
  214.      * @param string $nodeId 
  215.      * @return ezcTreeNodeList 
  216.      */
  217.     public function fetchSubtreeBreadthFirst$nodeId )
  218.     {
  219.         $className $this->properties['nodeClassName'];
  220.         $list new ezcTreeNodeList;
  221.         $list->addNodenew $className$this$nodeId ) );
  222.         $this->addChildNodesBreadthFirst$list$nodeId );
  223.         return $list;
  224.     }
  225.  
  226.     /**
  227.      * Returns the number of direct children of the node with ID $nodeId.
  228.      *
  229.      * @param string $nodeId 
  230.      * @return int 
  231.      */
  232.     public function getChildCount$nodeId )
  233.     {
  234.         $db $this->dbh;
  235.         $q $db->createSelectQuery();
  236.  
  237.         // SELECT count(id)
  238.         // FROM indexTable
  239.         // WHERE parent_id = $nodeId
  240.         $q->select'count(id)' )
  241.           ->from$db->quoteIdentifier$this->indexTableName ) )
  242.           ->where$q->expr->eq'parent_id'$q->bindValue$nodeId ) ) );
  243.  
  244.         $s $q->prepare();
  245.         $s->execute();
  246.         return (int) $s->fetchColumn);
  247.     }
  248.  
  249.     /**
  250.      * Adds the number of children with for the node with ID $nodeId nodes to
  251.      * $count, recursively.
  252.      *
  253.      * @param int $count 
  254.      * @param string $nodeId 
  255.      */
  256.     protected function countChildNodes&$count$nodeId )
  257.     {
  258.         foreach $this->fetchChildRecords$nodeId as $record )
  259.         {
  260.             $count++;
  261.             $this->countChildNodes$count$record['id');
  262.         }
  263.     }
  264.  
  265.     /**
  266.      * Returns the number of children of the node with ID $nodeId, recursively.
  267.      *
  268.      * @param string $nodeId 
  269.      * @return int 
  270.      */
  271.     public function getChildCountRecursive$nodeId )
  272.     {
  273.         $count 0;
  274.         $this->countChildNodes$count$nodeId );
  275.         return $count;
  276.     }
  277.  
  278.     /**
  279.      * Returns the distance from the root node to the node with ID $nodeId.
  280.      *
  281.      * @param string $nodeId 
  282.      * @return int 
  283.      */
  284.     public function getPathLength$nodeId )
  285.     {
  286.         $nodeId $this->getParentId$nodeId );
  287.         $length 0;
  288.  
  289.         while $nodeId !== null )
  290.         {
  291.             $nodeId $this->getParentId$nodeId );
  292.             $length++;
  293.         }
  294.         return $length;
  295.     }
  296.  
  297.     /**
  298.      * Returns whether the node with ID $nodeId has children.
  299.      *
  300.      * @param string $nodeId 
  301.      * @return bool 
  302.      */
  303.     public function hasChildNodes$nodeId )
  304.     {
  305.         return $this->getChildCount$nodeId 0;
  306.     }
  307.  
  308.     /**
  309.      * Returns whether the node with ID $childId is a direct child of the node
  310.      * with ID $parentId.
  311.      *
  312.      * @param string $childId 
  313.      * @param string $parentId 
  314.      * @return bool 
  315.      */
  316.     public function isChildOf$childId$parentId )
  317.     {
  318.         $nodeId $this->getParentId$childId );
  319.         $parentId = (string) $parentId;
  320.         return $parentId === $nodeId;
  321.     }
  322.  
  323.     /**
  324.      * Returns whether the node with ID $childId is a direct or indirect child
  325.      * of the node with ID $parentId.
  326.      *
  327.      * @param string $childId 
  328.      * @param string $parentId 
  329.      * @return bool 
  330.      */
  331.     public function isDescendantOf$childId$parentId )
  332.     {
  333.         $parentId = (string) $parentId;
  334.         $nodeId $childId;
  335.         do
  336.         {
  337.             $nodeId $this->getParentId$nodeId );
  338.             if $parentId === $nodeId )
  339.             {
  340.                 return true;
  341.             }
  342.         while $nodeId !== null );
  343.         return false;
  344.     }
  345.  
  346.     /**
  347.      * Returns whether the nodes with IDs $child1Id and $child2Id are siblings
  348.      * (ie, they share the same parent).
  349.      *
  350.      * @param string $child1Id 
  351.      * @param string $child2Id 
  352.      * @return bool 
  353.      */
  354.     public function isSiblingOf$child1Id$child2Id )
  355.     {
  356.         $nodeId1 $this->getParentId$child1Id );
  357.         $nodeId2 $this->getParentId$child2Id );
  358.         return $nodeId1 === $nodeId2 && (string) $child1Id !== (string) $child2Id;
  359.     }
  360.  
  361.     /**
  362.      * Sets a new node as root node, this also wipes out the whole tree.
  363.      *
  364.      * @param ezcTreeNode $node 
  365.      */
  366.     public function setRootNodeezcTreeNode $node )
  367.     {
  368.         $db $this->dbh;
  369.  
  370.         $q $db->createDeleteQuery();
  371.         $q->deleteFrom$db->quoteIdentifier$this->indexTableName ) );
  372.         $s $q->prepare();
  373.         $s->execute();
  374.         $this->store->deleteDataForAllNodes();
  375.  
  376.         $q $db->createInsertQuery();
  377.         $q->insertInto$db->quoteIdentifier$this->indexTableName ) )
  378.           ->set'parent_id'"null" )
  379.           ->set'id'$q->bindValue$node->id ) );
  380.         $s $q->prepare();
  381.         $s->execute();
  382.  
  383.         $this->store->storeDataForNode$node$node->data );
  384.     }
  385.  
  386.     /**
  387.      * Creates the query to insert an empty node into the database, so that the last-inserted ID can be obtained.
  388.      *
  389.      * @return ezcQueryInsert 
  390.      */
  391.     protected function createAddEmptyNodeQuery()
  392.     {
  393.         $db $this->dbh;
  394.  
  395.         $q $db->createInsertQuery();
  396.         $q->insertInto$db->quoteIdentifier$this->indexTableName ) )
  397.           ->set'parent_id'$q->bindValuenull ) );
  398.  
  399.         return $q;
  400.     }
  401.  
  402.     /**
  403.      * Adds the node $childNode as child of the node with ID $parentId.
  404.      *
  405.      * @param string $parentId 
  406.      * @param ezcTreeNode $childNode 
  407.      */
  408.     public function addChild$parentIdezcTreeNode $childNode )
  409.     {
  410.         if $this->inTransaction )
  411.         {
  412.             $this->addTransactionItemnew ezcTreeTransactionItemezcTreeTransactionItem::ADD$childNodenull$parentId ) );
  413.             return;
  414.         }
  415.  
  416.         $q $this->createAddNodeQuery$childNode->id );
  417.         $q->set'parent_id'$q->bindValue$parentId ) )
  418.           ->set'id'$q->bindValue$childNode->id ) );
  419.         $s $q->prepare();
  420.         $s->execute();
  421.  
  422.         $this->store->storeDataForNode$childNode$childNode->data );
  423.     }
  424.  
  425.     /**
  426.      * Deletes all nodes in the node list $list.
  427.      *
  428.      * @param ezcTreeNodeList $list 
  429.      */
  430.     private function deleteNodesezcTreeNodeList $list )
  431.     {
  432.         $db $this->dbh;
  433.         $q $db->createDeleteQuery();
  434.  
  435.         $nodeIdList array();
  436.         foreach array_keys$list->nodes as $nodeId )
  437.         {
  438.             $nodeIdList[= (string) $nodeId;
  439.         }
  440.  
  441.         // DELETE FROM indexTable
  442.         // WHERE id in ( $list );
  443.         $q->deleteFrom$db->quoteIdentifier$this->indexTableName ) );
  444.         $q->where$q->expr->in'id'$nodeIdList ) );
  445.         $s $q->prepare();
  446.         $s->execute();
  447.     }
  448.  
  449.     /**
  450.      * Deletes the node with ID $nodeId from the tree, including all its children.
  451.      *
  452.      * @param string $nodeId 
  453.      */
  454.     public function delete$nodeId )
  455.     {
  456.         if $this->inTransaction )
  457.         {
  458.             $this->addTransactionItemnew ezcTreeTransactionItemezcTreeTransactionItem::DELETEnull$nodeId ) );
  459.             return;
  460.         }
  461.  
  462.         $nodeList $this->fetchSubtree$nodeId );
  463.         $this->deleteNodes$nodeList );
  464.         $this->store->deleteDataForNodes$nodeList );
  465.     }
  466.  
  467.     /**
  468.      * Moves the node with ID $nodeId as child to the node with ID $targetParentId.
  469.      *
  470.      * @param string $nodeId 
  471.      * @param string $targetParentId 
  472.      */
  473.     public function move$nodeId$targetParentId )
  474.     {
  475.         if $this->inTransaction )
  476.         {
  477.             $this->addTransactionItemnew ezcTreeTransactionItemezcTreeTransactionItem::MOVEnull$nodeId$targetParentId ) );
  478.             return;
  479.         }
  480.  
  481.         $db $this->dbh;
  482.         $q $db->createUpdateQuery();
  483.  
  484.         $q->update$db->quoteIdentifier$this->indexTableName ) )
  485.           ->set'parent_id'$q->bindValue$targetParentId ) )
  486.           ->where$q->expr->eq'id'$q->bindValue$nodeId ) ) );
  487.  
  488.         $s $q->prepare();
  489.         $s->execute();
  490.     }
  491.  
  492.     /**
  493.      * Fixates the transaction.
  494.      */
  495.     public function fixateTransaction()
  496.     {
  497.     }
  498. }
  499. ?>
Documentation generated by phpDocumentor 1.4.3