Author: dr
Date: Wed Jul 25 15:19:19 2007
New Revision: 5730

Log:
- Commit the rest of the prototype.

Added:
    experimental/Tree/src/exceptions/exception.php   (with props)
    experimental/Tree/src/exceptions/invalid_id.php   (with props)
    experimental/Tree/src/structs/
    experimental/Tree/src/structs/transaction_item.php   (with props)
Modified:
    experimental/Tree/src/backends/db.php
    experimental/Tree/src/backends/db_parent_child.php
    experimental/Tree/src/backends/xml.php
    experimental/Tree/src/interfaces/backend.php
    experimental/Tree/src/interfaces/data_store.php
    experimental/Tree/src/stores/external_db.php
    experimental/Tree/src/stores/internal_xml.php
    experimental/Tree/src/tree.php
    experimental/Tree/src/tree_autoload.php
    experimental/Tree/src/tree_node.php

Modified: experimental/Tree/src/backends/db.php
==============================================================================
--- experimental/Tree/src/backends/db.php [iso-8859-1] (original)
+++ experimental/Tree/src/backends/db.php [iso-8859-1] Wed Jul 25 15:19:19 2007
@@ -41,7 +41,7 @@
 
         $q->select( 'id' )
           ->from( $db->quoteIdentifier( $this->indexTableName ) )
-          ->where( 'id', $q->bindValue( $id ) );
+          ->where( $q->expr->eq( 'id', $q->bindValue( $id ) ) );
 
         $s = $q->prepare();
         $s->execute();
@@ -57,7 +57,7 @@
     {
     }
 
-    public function fetchSubtree( $id )
+    public function fetchSubtree( $id, $searchMethod = ezcTree::DEPTH_FIRST )
     {
     }
 
@@ -65,11 +65,15 @@
     {
     }
 
+    public function getChildCountRecursive( $id )
+    {
+    }
+
     public function getPathLength( $id )
     {
     }
 
-    public function hasChildren( $id )
+    public function hasChildNodes( $id )
     {
     }
 
@@ -96,17 +100,5 @@
     public function move( $id, $targetParentId )
     {
     }
-
-    public function beginTransaction()
-    {
-    }
-
-    public function commit()
-    {
-    }
-
-    public function rollback()
-    {
-    }
 }
 ?>

Modified: experimental/Tree/src/backends/db_parent_child.php
==============================================================================
--- experimental/Tree/src/backends/db_parent_child.php [iso-8859-1] (original)
+++ experimental/Tree/src/backends/db_parent_child.php [iso-8859-1] Wed Jul 25 
15:19:19 2007
@@ -46,6 +46,21 @@
         return $parentId === $id;
     }
 
+    public function isDecendantOf( $childId, $parentId )
+    {
+        $parentId = (string) $parentId;
+        $id = $childId;
+        do
+        {
+            $id = $this->getParentId( $id );
+            if ( $parentId === $id )
+            {
+                return true;
+            }
+        } while ( $id !== null );
+        return false;
+    }
+
     public function isSiblingOf( $child1Id, $child2Id )
     {
         $id1 = $this->getParentId( $child1Id );
@@ -77,7 +92,34 @@
         }
     }
 
-    public function fetchSubtree( $nodeId )
+    public function fetchChildren( $id )
+    {
+        $className = $this->properties['nodeClassName'];
+        $list = new ezcTreeNodeList;
+        foreach ( $this->fetchChildRecords( $id ) as $record )
+        {
+            $list->addNode( $record['id'], new $className( $this, 
$record['id'] ) );
+        }
+        return $list;
+    }
+
+    public function fetchPath( $id )
+    {
+        $className = $this->properties['nodeClassName'];
+        $list = new ezcTreeNodeList;
+        $list->addNode( $id, new $className( $this, $id ) );
+
+        $id = $this->getParentId( $id );
+
+        while ( $id != null )
+        {
+            $list->addNode( $id, new $className( $this, $id ) );
+            $id = $this->getParentId( $id );
+        }
+        return $list;
+    }
+
+    public function fetchSubtree( $nodeId, $searchMethod = 
ezcTree::DEPTH_FIRST )
     {
         $className = $this->properties['nodeClassName'];
         $list = new ezcTreeNodeList;
@@ -85,5 +127,143 @@
         $this->addChildNodes( $list, $nodeId );
         return $list;
     }
+
+    public function getChildCount( $nodeId )
+    {
+        $db = $this->dbh;
+        $q = $db->createSelectQuery();
+
+        $q->select( 'count(id)' )
+          ->from( $db->quoteIdentifier( $this->indexTableName ) )
+          ->where( $q->expr->eq( 'parent_id', $q->bindValue( $nodeId ) ) );
+
+        $s = $q->prepare();
+        $s->execute();
+        return (int) $s->fetchColumn(0);
+    }
+
+    private function countChildNodes( &$count, $nodeId )
+    {
+        foreach ( $this->fetchChildRecords( $nodeId ) as $record )
+        {
+            $count++;
+            $this->countChildNodes( $count, $record['id'] );
+        }
+    }
+
+    public function getChildCountRecursive( $id )
+    {
+        $count = 0;
+        $this->countChildNodes( $count, $id );
+        return $count;
+    }
+
+    public function getPathLength( $id )
+    {
+        $id = $this->getParentId( $id );
+        $length = 0;
+
+        while ( $id !== null )
+        {
+            $id = $this->getParentId( $id );
+            $length++;
+        }
+        return $length;
+    }
+
+    public function hasChildNodes( $nodeId )
+    {
+        return $this->getChildCount( $nodeId ) > 0;
+    }
+
+
+    public function setRootNode( ezcTreeNode $node )
+    {
+        $db = $this->dbh;
+
+        $q = $db->createDeleteQuery();
+        $q->deleteFrom( $db->quoteIdentifier( $this->indexTableName ) );
+        $s = $q->prepare();
+        $s->execute();
+
+        $q = $db->createInsertQuery();
+        $q->insertInto( $db->quoteIdentifier( $this->indexTableName ) )
+          ->set( 'parent_id', "null" )
+          ->set( 'id', $q->bindValue( $node->id ) );
+        $s = $q->prepare();
+        $s->execute();
+
+        $this->store->storeDataForNode( $node, $node->data );
+    }
+
+    public function addChild( $parentId, ezcTreeNode $childNode )
+    {
+        if ( $this->inTransaction )
+        {
+            $this->addTransactionItem( new ezcTreeTransactionItem( 
ezcTreeTransactionItem::ADD, $childNode, null, $parentId ) );
+            return;
+        }
+
+        $db = $this->dbh;
+
+        $q = $db->createInsertQuery();
+        $q->insertInto( $db->quoteIdentifier( $this->indexTableName ) )
+          ->set( 'parent_id', $q->bindValue( $parentId ) )
+          ->set( 'id', $q->bindValue( $childNode->id ) );
+        $s = $q->prepare();
+        $s->execute();
+
+        $this->store->storeDataForNode( $childNode, $childNode->data );
+    }
+
+    public function move( $id, $targetParentId )
+    {
+        if ( $this->inTransaction )
+        {
+            $this->addTransactionItem( new ezcTreeTransactionItem( 
ezcTreeTransactionItem::MOVE, null, $id, $targetParentId ) );
+            return;
+        }
+
+        $db = $this->dbh;
+        $q = $db->createUpdateQuery();
+
+        $q->update( $db->quoteIdentifier( $this->indexTableName ) )
+          ->set( 'parent_id', $q->bindValue( $targetParentId ) )
+          ->where( $q->expr->eq( 'id', $q->bindValue( $id ) ) );
+
+        $s = $q->prepare();
+        $s->execute();
+    }
+
+    protected function deleteChildNodes( $nodeId )
+    {
+        $db = $this->dbh;
+        $q = $db->createDeleteQuery();
+
+        foreach ( $this->fetchChildRecords( $nodeId ) as $record )
+        {
+            $this->deleteChildNodes( $record['id'] );
+        }
+
+        $q->deleteFrom( $db->quoteIdentifier( $this->indexTableName ) )
+          ->where( $q->expr->eq( 'id', $q->bindValue( $nodeId ) ) );
+        $s = $q->prepare();
+        $s->execute();
+    }
+
+    public function delete( $id )
+    {
+        if ( $this->inTransaction )
+        {
+            $this->addTransactionItem( new ezcTreeTransactionItem( 
ezcTreeTransactionItem::DELETE, null, $id ) );
+            return;
+        }
+
+        $this->deleteChildNodes( $id );
+    }
+
+    public function fixateTransaction()
+    {
+    }
 }
 ?>

Modified: experimental/Tree/src/backends/xml.php
==============================================================================
--- experimental/Tree/src/backends/xml.php [iso-8859-1] (original)
+++ experimental/Tree/src/backends/xml.php [iso-8859-1] Wed Jul 25 15:19:19 2007
@@ -91,33 +91,145 @@
         return ( $elem !== NULL ) ? true : false;
     }
 
+    private function getNodeById( $id )
+    {
+        $node = $this->dom->getElementById( "id$id" );
+        if ( !$node )
+        {
+            throw new ezcTreeInvalidIdException( $id );
+        }
+        return $node;
+    }
+
     public function fetchChildren( $id )
     {
+        $className = $this->properties['nodeClassName'];
+        $list = new ezcTreeNodeList;
+        foreach ( $this->fetchChildRecords( $id ) as $record )
+        {
+            $list->addNode( $record['id'], new $className( $this, 
$record['id'] ) );
+        }
+        return $list;
     }
 
     public function fetchPath( $id )
     {
-    }
-
-    public function fetchSubtree( $id )
-    {
-    }
+        $className = $this->properties['nodeClassName'];
+        $list = new ezcTreeNodeList;
+        $list->addNode( $id, new $className( $this, $id ) );
+
+        $elem = $this->dom->getElementById( "id$id" );
+        $elem = $elem->parentNode;
+
+        while ( $elem !== null && $elem->nodeType == XML_ELEMENT_NODE && 
$elem->tagName == 'node' )
+        {
+            $id = substr( $elem->getAttribute( 'id' ), 2 );
+            $list->addNode( $id, new $className( $this, $id ) );
+            $elem = $elem->parentNode;
+        }
+        return $list;
+    }
+
+
+    private function fetchChildRecords( $nodeId )
+    {
+        $childNodes = array();
+        $elem = $this->getNodeById( $nodeId );
+        $children = $elem->childNodes;
+        foreach ( $children as $child )
+        {
+            if ( $child->nodeType === XML_ELEMENT_NODE && $child->tagName == 
"node" )
+            {
+                $id = $child->getAttribute( 'id' );
+                $childNodes[] = array( 'id' => substr( $id, 2 ) );
+            }
+        }
+        return $childNodes;
+    }
+
+    private function addChildNodes( $list, $nodeId )
+    {
+        $className = $this->properties['nodeClassName'];
+        foreach ( $this->fetchChildRecords( $nodeId ) as $record )
+        {
+            $list->addNode( $record['id'], new $className( $this, 
$record['id'] ) );
+            $this->addChildNodes( $list, $record['id'] );
+        }
+    }
+
+    public function fetchSubtree( $nodeId, $searchMethod = 
ezcTree::DEPTH_FIRST )
+    {
+        $className = $this->properties['nodeClassName'];
+        $list = new ezcTreeNodeList;
+        $list->addNode( $nodeId, new $className( $this, $nodeId ) );
+        $this->addChildNodes( $list, $nodeId );
+        return $list;
+    }
+
+
 
     public function getChildCount( $id )
     {
+        $count = 0;
+        $elem = $this->getNodeById( $id );
+        $children = $elem->childNodes;
+        foreach ( $children as $child )
+        {
+            if ( $child->nodeType === XML_ELEMENT_NODE && $child->tagName == 
"node" )
+            {
+                $count++;
+            }
+        }
+        return $count;
+    }
+
+    private function countChildNodes( &$count, $nodeId )
+    {
+        foreach ( $this->fetchChildRecords( $nodeId ) as $record )
+        {
+            $count++;
+            $this->countChildNodes( $count, $record['id'] );
+        }
+    }
+
+    public function getChildCountRecursive( $id )
+    {
+        $count = 0;
+        $this->countChildNodes( $count, $id );
+        return $count;
     }
 
     public function getPathLength( $id )
     {
-    }
-
-    public function hasChildren( $id )
-    {
+        $elem = $this->getNodeById( $id );
+        $elem = $elem->parentNode;
+        $length = -1;
+
+        while ( $elem !== null && $elem->nodeType == XML_ELEMENT_NODE )
+        {
+            $elem = $elem->parentNode;
+            $length++;
+        }
+        return $length;
+    }
+
+    public function hasChildNodes( $id )
+    {
+        $elem = $this->getNodeById( $id );
+        $children = $elem->childNodes;
+        foreach ( $children as $child )
+        {
+            if ( $child->nodeType === XML_ELEMENT_NODE && $child->tagName == 
"node" )
+            {
+                return true;
+            }
+        }
+        return false;
     }
 
     public function isChildOf( $childId, $parentId )
     {
-        $elem = $this->dom->getElementById( "id$childId" );
+        $elem = $this->getNodeById( $childId );
         $parentElem = $elem->parentNode;
         $id = $parentElem->getAttribute( 'id' );
         if ( $id === "id$parentId" )
@@ -129,10 +241,29 @@
 
     public function isDecendantOf( $childId, $parentId )
     {
-    }
-
-    public function isSiblingOf( $childId, $parentId )
-    {
+        $elem = $this->getNodeById( $childId );
+        $elem = $elem->parentNode;
+
+        while ( $elem !== null && $elem->nodeType == XML_ELEMENT_NODE )
+        {
+            $id = $elem->getAttribute( 'id' );
+            if ( $id === "id$parentId" )
+            {
+                    return true;
+            }
+            $elem = $elem->parentNode;
+        }
+        return false;
+    }
+
+    public function isSiblingOf( $child1Id, $child2Id )
+    {
+        $elem1 = $this->getNodeById( $child1Id );
+        $elem2 = $this->getNodeById( $child2Id );
+        return (
+            ( $child1Id !== $child2Id ) && 
+            ( $elem1->parentNode->getAttribute( 'id' ) === 
$elem2->parentNode->getAttribute( 'id' ) )
+        );
     }
 
     public function setRootNode( ezcTreeNode $node )
@@ -156,8 +287,14 @@
 
     public function addChild( $parentId, ezcTreeNode $childNode )
     {
+        if ( $this->inTransaction )
+        {
+            $this->addTransactionItem( new ezcTreeTransactionItem( 
ezcTreeTransactionItem::ADD, $childNode, null, $parentId ) );
+            return;
+        }
+
         // locate parent node
-        $elem = $this->dom->getElementById( "id{$parentId}" );
+        $elem = $this->getNodeById( $parentId );
 
         // Create new DOM node
         $child = $this->dom->createElement( 'node' );
@@ -167,27 +304,58 @@
         // Append to parent node
         $elem->appendChild( $child );
         $this->store->storeDataForNode( $childNode, $childNode->data );
+
+        if ( !$this->inTransactionCommit )
+        {
+            $this->saveFile();
+        }
+    }
+
+    public function delete( $id )
+    {
+        if ( $this->inTransaction )
+        {
+            $this->addTransactionItem( new ezcTreeTransactionItem( 
ezcTreeTransactionItem::DELETE, null, $id ) );
+            return;
+        }
+
+        // locate node to move
+        $nodeToDelete = $this->getNodeById( $id );
+
+        // Use the parent to remove the child
+        $nodeToDelete->parentNode->removeChild( $nodeToDelete );
+
+        if ( !$this->inTransactionCommit )
+        {
+            $this->saveFile();
+        }
+    }
+
+    public function move( $id, $targetParentId )
+    {
+        if ( $this->inTransaction )
+        {
+            $this->addTransactionItem( new ezcTreeTransactionItem( 
ezcTreeTransactionItem::MOVE, null, $id, $targetParentId ) );
+            return;
+        }
+
+        // locate node to move
+        $nodeToMove = $this->getNodeById( $id );
+
+        // locate new parent
+        $parent = $this->getNodeById( $targetParentId );
+
+        $parent->appendChild( $nodeToMove );
+
+        if ( !$this->inTransactionCommit )
+        {
+            $this->saveFile();
+        }
+    }
+
+    public function fixateTransaction()
+    {
         $this->saveFile();
-    }
-
-    public function delete( $id )
-    {
-    }
-
-    public function move( $id, $targetParentId )
-    {
-    }
-
-    public function beginTransaction()
-    {
-    }
-
-    public function commit()
-    {
-    }
-
-    public function rollback()
-    {
     }
 }
 ?>

Added: experimental/Tree/src/exceptions/exception.php
==============================================================================
--- experimental/Tree/src/exceptions/exception.php (added)
+++ experimental/Tree/src/exceptions/exception.php [iso-8859-1] Wed Jul 25 
15:19:19 2007
@@ -1,0 +1,21 @@
+<?php
+/**
+ * File containing the ezcConfigurationException class
+ *
+ * @package Configuration
+ * @version //autogen//
+ * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ */
+
+/**
+ * This class provides an exception container for use with the Configuration
+ * component.
+ *
+ * @package Configuration
+ * @version //autogen//
+ */
+abstract class ezcTreeException extends ezcBaseException
+{
+}
+?>

Propchange: experimental/Tree/src/exceptions/exception.php
------------------------------------------------------------------------------
    svn:eol-style = native

Added: experimental/Tree/src/exceptions/invalid_id.php
==============================================================================
--- experimental/Tree/src/exceptions/invalid_id.php (added)
+++ experimental/Tree/src/exceptions/invalid_id.php [iso-8859-1] Wed Jul 25 
15:19:19 2007
@@ -1,0 +1,31 @@
+<?php
+/**
+ * File containing the ezcConfigurationException class
+ *
+ * @package Configuration
+ * @version //autogen//
+ * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ */
+
+/**
+ * Exception that is thrown if a group is tried to be added, while it already
+ * exists.
+ *
+ * @package Configuration
+ * @version //autogen//
+ */
+class ezcTreeInvalidIdException extends ezcTreeException
+{
+    /**
+     * Constructs a new ezcTreeException for the ID $id.
+     *
+     * @param string $groupName
+     * @return void
+     */
+    function __construct( $id )
+    {
+        parent::__construct( "The node with ID '{$id}' could not be found." );
+    }
+}
+?>

Propchange: experimental/Tree/src/exceptions/invalid_id.php
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: experimental/Tree/src/interfaces/backend.php
==============================================================================
--- experimental/Tree/src/interfaces/backend.php [iso-8859-1] (original)
+++ experimental/Tree/src/interfaces/backend.php [iso-8859-1] Wed Jul 25 
15:19:19 2007
@@ -23,20 +23,21 @@
      * @param string $id
      * @return ezcTreeNode
      */
-    public function fetchById( $id );
+    public function fetchNodeById( $id );
 
     public function fetchChildren( $id );
     public function fetchPath( $id );
-    public function fetchSubtree( $id );
+    public function fetchSubtree( $id, $searchMethod = ezcTree::DEPTH_FIRST );
 
     public function getChildCount( $id );
+    public function getChildCountRecursive( $id );
     public function getPathLength( $id );
 
-    public function hasChildren( $id );
+    public function hasChildNodes( $id );
 
     public function isChildOf( $childId, $parentId );
     public function isDecendantOf( $childId, $parentId );
-    public function isSiblingOf( $childId, $parentId );
+    public function isSiblingOf( $child1Id, $child2Id );
 
     public function nodeExists( $id );
     public function createNode( $id, $data );
@@ -48,5 +49,6 @@
     public function beginTransaction();
     public function commit();
     public function rollback();
+    public function fixateTransaction();
 }
 ?>

Modified: experimental/Tree/src/interfaces/data_store.php
==============================================================================
--- experimental/Tree/src/interfaces/data_store.php [iso-8859-1] (original)
+++ experimental/Tree/src/interfaces/data_store.php [iso-8859-1] Wed Jul 25 
15:19:19 2007
@@ -18,6 +18,7 @@
 interface ezcTreeDataStore
 {
     public function fetchDataForNode( ezcTreeNode $node );
+    public function fetchDataForNodes( array $nodes );
     public function storeDataForNode( ezcTreeNode $node, $data );
 }
 ?>

Modified: experimental/Tree/src/stores/external_db.php
==============================================================================
--- experimental/Tree/src/stores/external_db.php [iso-8859-1] (original)
+++ experimental/Tree/src/stores/external_db.php [iso-8859-1] Wed Jul 25 
15:19:19 2007
@@ -59,6 +59,10 @@
         return $this->wantedData( $s );
     }
 
+    public function fetchDataForNodes( array $nodes )
+    {
+    }
+
     private function wantedData( PDOStatement $s )
     {
         $data = $s->fetch();

Modified: experimental/Tree/src/stores/internal_xml.php
==============================================================================
--- experimental/Tree/src/stores/internal_xml.php [iso-8859-1] (original)
+++ experimental/Tree/src/stores/internal_xml.php [iso-8859-1] Wed Jul 25 
15:19:19 2007
@@ -31,6 +31,10 @@
         return $elem->getElementsByTagNameNS( 
'http://components.ez.no/Tree/data', 'data' )->item(0)->firstChild->data;
     }
 
+    public function fetchDataForNodes( array $nodes )
+    {
+    }
+
     public function storeDataForNode( ezcTreeNode $node, $data )
     {
         $id = $node->id;

Added: experimental/Tree/src/structs/transaction_item.php
==============================================================================
--- experimental/Tree/src/structs/transaction_item.php (added)
+++ experimental/Tree/src/structs/transaction_item.php [iso-8859-1] Wed Jul 25 
15:19:19 2007
@@ -1,0 +1,87 @@
+<?php
+/**
+ * @copyright Copyright (C) 2005-2007 eZ systems as. All rights reserved.
+ * @license http://ez.no/licenses/new_bsd New BSD License
+ * @version //autogentag//
+ * @filesource
+ * @package Tree
+ */
+
+/**
+ * A container to store one INI settings item
+ *
+ * This struct is used in various classes to store the data accompanying one
+ * INI setting.
+ *
+ * @package Tree
+ * @version //autogentag//
+ */
+class ezcTreeTransactionItem extends ezcBaseStruct
+{
+    /**
+     * 
+     *
+     * @var int
+     */
+    const ADD = 1;
+
+    /**
+     * 
+     *
+     * @var int
+     */
+    const DELETE = 2;
+
+    /**
+     * 
+     *
+     * @var int
+     */
+    const MOVE = 3;
+
+    /**
+     * The item type.
+     *
+     * Either ADD, DELETE or MOVE
+     *
+     * @var int
+     */
+    public $type;
+
+    /**
+     * 
+     *
+     * @var ezcTreeNode
+     */
+    public $node;
+
+    /**
+     * 
+     *
+     * @var string
+     */
+    public $nodeId;
+
+    /**
+     * 
+     *
+     * @var string
+     */
+    public $parentId;
+    /**
+     * Constructs an ezcTreeTransactionItem object.
+     *
+     * @param int $type Either ADD, DELETE or REMOVE
+     * @param ezcTreeNode $node
+     * @param string $nodeId
+     * @param string $parentId
+     */
+    function __construct( $type, $node = null, $nodeId = null, $parentId = 
null )
+    {
+        $this->type = $type;
+        $this->node = $node;
+        $this->nodeId = $nodeId;
+        $this->parentId = $parentId;
+    }
+}
+?>

Propchange: experimental/Tree/src/structs/transaction_item.php
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: experimental/Tree/src/tree.php
==============================================================================
--- experimental/Tree/src/tree.php [iso-8859-1] (original)
+++ experimental/Tree/src/tree.php [iso-8859-1] Wed Jul 25 15:19:19 2007
@@ -1,6 +1,7 @@
 <?php
 abstract class ezcTree
 {
+    const DEPTH_FIRST = 1;
     const RECURSIVE = 1;
 
     /**
@@ -10,8 +11,13 @@
      */
     protected $properties = array();
 
+    protected $inTransaction = false;
+    protected $inTransactionCommit = false;
+    private $transactionList = array();
+
     public function __construct()
     {
+        $this->properties['prefetch'] = false;
         $this->properties['nodeClassName'] = 'ezcTreeNode';
     }
 
@@ -27,8 +33,8 @@
         {
             case 'store':
             case 'nodeClassName':
+            case 'prefetch':
                 return $this->properties[$name];
-
         }
         throw new ezcBasePropertyNotFoundException( $name );
     }
@@ -58,9 +64,17 @@
                 // here unfortunately
                 $parentClass = new ReflectionClass( 'ezcTreeNode' );
                 $handlerClass = new ReflectionClass( $propertyValue );
-                if ( 'ezcMail' !== $propertyValue && 
!$handlerClass->isSubclassOf( $parentClass ) )
+                if ( 'ezcTreeNode' !== $propertyValue && 
!$handlerClass->isSubclassOf( $parentClass ) )
                 {
                     throw new ezcBaseInvalidParentClassException( 
'ezcTreeNode', $propertyValue );
+                }
+                $this->properties[$propertyName] = $propertyValue;
+                break;
+
+            case 'prefetch':
+                if ( !is_bool( $propertyValue ) )
+                {
+                    throw new ezcBaseValueException( $propertyName, 
$propertyValue, 'boolean' );
                 }
                 $this->properties[$propertyName] = $propertyValue;
                 break;
@@ -82,13 +96,71 @@
      * @param string $id
      * @return ezcTreeNode
      */
-    public function fetchById( $id )
+    public function fetchNodeById( $id )
     {
+        if ( !$this->nodeExists( $id ) )
+        {
+            throw new ezcTreeInvalidIdException( $id );
+        }
         $className = $this->properties['nodeClassName'];
-        // Obtain data from the store
         $node = new $className( $this, $id );
-        $node->data = $this->properties['store']->fetchDataForNode( $node );
+
+        // Obtain data from the store if prefetch is enabled
+        if ( $this->prefetch )
+        {
+            $node->data = $this->properties['store']->fetchDataForNode( $node 
);
+        }
         return $node;
+    }
+
+    public function beginTransaction()
+    {
+        if ( $this->inTransaction )
+        {
+            throw new ezcTreeTransactionAlreadyStartedException;
+        }
+        $this->inTransaction = true;
+        $this->transactionList = array();
+    }
+
+    public function commit()
+    {
+        $this->inTransaction = false;
+        $this->inTransactionCommit = true;
+        foreach ( $this->transactionList as $transactionItem )
+        {
+            switch ( $transactionItem->type )
+            {
+                case ezcTreeTransactionItem::ADD:
+                    $this->addChild( $transactionItem->parentId, 
$transactionItem->node );
+                    break;
+
+                case ezcTreeTransactionItem::DELETE:
+                    $this->delete( $transactionItem->nodeId );
+                    break;
+
+                case ezcTreeTransactionItem::MOVE:
+                    $this->move( $transactionItem->nodeId, 
$transactionItem->parentId );
+                    break;
+            }
+        }
+        $this->inTransactionCommit = false;
+        $this->fixateTransaction();
+    }
+
+    protected function addTransactionItem( ezcTreeTransactionItem $item )
+    {
+        if ( !$this->inTransaction )
+        {
+            throw new ezcTreeTransactionNotStartedException;
+        }
+        $this->transactionList[] = $item;
+    }
+
+    public function rollback()
+    {
+        $this->inTransaction = false;
+        $this->transactionList = array();
     }
 }
 ?>

Modified: experimental/Tree/src/tree_autoload.php
==============================================================================
--- experimental/Tree/src/tree_autoload.php [iso-8859-1] (original)
+++ experimental/Tree/src/tree_autoload.php [iso-8859-1] Wed Jul 25 15:19:19 
2007
@@ -10,6 +10,8 @@
  */
 
 return array(
+    'ezcTreeException'                => 'Tree/exceptions/exception.php',
+    'ezcTreeInvalidIdException'       => 'Tree/exceptions/invalid_id.php',
     'ezcTree'                         => 'Tree/tree.php',
     'ezcTreeBackend'                  => 'Tree/interfaces/backend.php',
     'ezcTreeDataStore'                => 'Tree/interfaces/data_store.php',
@@ -21,6 +23,7 @@
     'ezcTreeNode'                     => 'Tree/tree_node.php',
     'ezcTreeNodeList'                 => 'Tree/tree_node_list.php',
     'ezcTreeNodeListIterator'         => 'Tree/tree_node_list_iterator.php',
+    'ezcTreeTransactionItem'          => 'Tree/structs/transaction_item.php',
     'ezcTreeXml'                      => 'Tree/backends/xml.php',
     'ezcTreeXmlInternalDataStore'     => 'Tree/stores/internal_xml.php',
 );

Modified: experimental/Tree/src/tree_node.php
==============================================================================
--- experimental/Tree/src/tree_node.php [iso-8859-1] (original)
+++ experimental/Tree/src/tree_node.php [iso-8859-1] Wed Jul 25 15:19:19 2007
@@ -48,8 +48,15 @@
     {
         switch ( $name )
         {
+
+            case 'data':
+                if ( $this->properties['data'] === null )
+                {
+                    // fetch the data on the fly
+                    $this->properties['data'] = 
$this->tree->store->fetchDataForNode( $this );
+                }
+                // break intentionally missing
             case 'id':
-            case 'data':
                 return $this->properties[$name];
 
         }
@@ -86,10 +93,12 @@
 
     public function fetchChildren()
     {
+        return $this->tree->fetchChildren( $this->id );
     }
 
     public function fetchPath()
     {
+        return $this->tree->fetchPath( $this->id );
     }
 
     public function fetchSubtree()
@@ -102,12 +111,19 @@
         return $this->tree->getChildCount( $this->id );
     }
 
+    public function getChildCountRecursive()
+    {
+        return $this->tree->getChildCountRecursive( $this->id );
+    }
+
     public function getPathLength()
     {
+        return $this->tree->getPathlength( $this->id );
     }
 
-    public function hasChildren()
+    public function hasChildNodes()
     {
+        return $this->tree->hasChildNodes( $this->id );
     }
 
     public function isChildOf( ezcTreeNode $parentNode )
@@ -117,6 +133,7 @@
 
     public function isDecendantOf( ezcTreeNode $parentNode )
     {
+        return $this->tree->isDecendantOf( $this->id, $parentNode->id );
     }
 
     public function isSiblingOf( ezcTreeNode $child2Node )


-- 
svn-components mailing list
[email protected]
http://lists.ez.no/mailman/listinfo/svn-components

Reply via email to