Forráskód Böngészése

[Tree] Materialized Path (ORM): Now a tree from a specific root node can be built.

comfortablynumb 13 éve
szülő
commit
0c560ee51b

+ 26 - 15
lib/Gedmo/Tree/Entity/Repository/MaterializedPathRepository.php

@@ -24,31 +24,37 @@ class MaterializedPathRepository extends AbstractTreeRepository
     /**
      * Get tree query builder
      *
+     * @param object Root node
+     *
      * @return Doctrine\ORM\QueryBuilder
      */
-    public function getTreeQueryBuilder()
+    public function getTreeQueryBuilder($rootNode = null)
     {
-        return $this->getChildrenQueryBuilder();
+        return $this->getChildrenQueryBuilder($rootNode, false, null, 'asc', true);
     }
 
     /**
      * Get tree query
      *
+     * @param object Root node
+     *
      * @return Doctrine\ORM\Query
      */
-    public function getTreeQuery()
+    public function getTreeQuery($rootNode = null)
     {
-        return $this->getTreeQueryBuilder()->getQuery();
+        return $this->getTreeQueryBuilder($rootNode)->getQuery();
     }
 
     /**
      * Get tree
      *
+     * @param object Root node
+     *
      * @return array
      */
-    public function getTree()
+    public function getTree($rootNode = null)
     {
-        return $this->getTreeQuery()->execute();
+        return $this->getTreeQuery($rootNode)->execute();
     }
 
     /**
@@ -86,7 +92,7 @@ class MaterializedPathRepository extends AbstractTreeRepository
      *
      * @return Doctrine\ORM\QueryBuilder
      */
-    public function getChildrenQueryBuilder($node = null, $direct = false, $sortByField = null, $direction = 'asc')
+    public function getChildrenQueryBuilder($node = null, $direct = false, $sortByField = null, $direction = 'asc', $includeNode = false)
     {
         $meta = $this->getClassMetadata();
         $config = $this->listener->getConfiguration($this->_em, $meta->name);
@@ -96,6 +102,7 @@ class MaterializedPathRepository extends AbstractTreeRepository
         $qb = $this->_em->createQueryBuilder($meta->name)
             ->select($alias)
             ->from($meta->name, $alias);
+        $expr = '';
 
         if (is_object($node) && $node instanceof $meta->name) {
             $node = new EntityWrapper($node, $this->_em);
@@ -103,7 +110,10 @@ class MaterializedPathRepository extends AbstractTreeRepository
             $expr = $qb->expr()->andx()->add(
                 $qb->expr()->like($alias.'.'.$path, $qb->expr()->literal($nodePath.'%'))
             );
-            $expr->add($qb->expr()->neq($alias.'.'.$path, $qb->expr()->literal($nodePath)));
+
+            if (!$includeNode) {
+                $expr->add($qb->expr()->neq($alias.'.'.$path, $qb->expr()->literal($nodePath)));
+            }
 
             if ($direct) {
                 $expr->add(
@@ -111,12 +121,13 @@ class MaterializedPathRepository extends AbstractTreeRepository
                         $qb->expr()->like($alias.'.'.$path, $qb->expr()->literal($nodePath.'%'.$separator.'%'.$separator))
                 ));
             }
-
-            $qb->where('('.$expr.')');
         } else if ($direct) {
             $expr = $qb->expr()->not(
                 $qb->expr()->like($alias.'.'.$path, $qb->expr()->literal('%'.$separator.'%'.$separator.'%'))
             );
+        }
+
+        if ($expr) {
             $qb->where('('.$expr.')');
         }
 
@@ -132,9 +143,9 @@ class MaterializedPathRepository extends AbstractTreeRepository
      *
      * @return Doctrine\ORM\Query
      */
-    public function getChildrenQuery($node = null, $direct = false, $sortByField = null, $direction = 'asc')
+    public function getChildrenQuery($node = null, $direct = false, $sortByField = null, $direction = 'asc', $includeNode = false)
     {
-        return $this->getChildrenQueryBuilder($node, $direct, $sortByField, $direction)->getQuery();
+        return $this->getChildrenQueryBuilder($node, $direct, $sortByField, $direction, $includeNode)->getQuery();
     }
 
     /**
@@ -142,9 +153,9 @@ class MaterializedPathRepository extends AbstractTreeRepository
      *
      * @return array
      */
-    public function getChildren($node = null, $direct = false, $sortByField = null, $direction = 'asc')
+    public function getChildren($node = null, $direct = false, $sortByField = null, $direction = 'asc', $includeNode = false)
     {
-        return $this->getChildrenQuery($node, $direct, $sortByField, $direction)->execute();
+        return $this->getChildrenQuery($node, $direct, $sortByField, $direction, $includeNode)->execute();
     }
 
     /**
@@ -161,7 +172,7 @@ class MaterializedPathRepository extends AbstractTreeRepository
             $sortBy = array_merge($sortBy, $options['childSort']);
         }
 
-        return $this->getChildrenQueryBuilder($node, $direct, $sortBy['field'], $sortBy['dir']);
+        return $this->getChildrenQueryBuilder($node, $direct, $sortBy['field'], $sortBy['dir'], true);
     }
 
     /**

+ 4 - 0
tests/Gedmo/Tree/MaterializedPathODMMongoDBRepositoryTest.php

@@ -161,6 +161,10 @@ class MaterializedPathODMMongoDBRepositoryTest extends BaseTestCaseMongoODM
         // Tree of one specific root
         $roots = $repo->getRootNodes();
         $tree = $repo->childrenHierarchy($roots->getNext());
+
+        $this->assertEquals('Drinks', $tree[0]['title']);
+        $this->assertEquals('Whisky', $tree[0]['__children'][0]['title']);
+        $this->assertEquals('Best Whisky', $tree[0]['__children'][0]['__children'][0]['title']);
     }
 
     protected function getUsedEntityFixtures()

+ 95 - 27
tests/Gedmo/Tree/MaterializedPathORMRepositoryTest.php

@@ -43,9 +43,10 @@ class MaterializedPathORMRepositoryTest extends BaseTestCaseORM
         $repo = $this->em->getRepository(self::CATEGORY);
         $result = $repo->getRootNodes('title');
         
-        $this->assertCount(2, $result);
-        $this->assertEquals('Food', $result[0]->getTitle());
-        $this->assertEquals('Sports', $result[1]->getTitle());
+        $this->assertCount(3, $result);
+        $this->assertEquals('Drinks', $result[0]->getTitle());
+        $this->assertEquals('Food', $result[1]->getTitle());
+        $this->assertEquals('Sports', $result[2]->getTitle());
     }
 
     /**
@@ -56,7 +57,7 @@ class MaterializedPathORMRepositoryTest extends BaseTestCaseORM
         $repo = $this->em->getRepository(self::CATEGORY);
         $root = $repo->findOneByTitle('Food');
 
-        // Get all children from the root
+        // Get all children from the root, NOT including it
         $result = $repo->getChildren($root, false, 'title');
 
         $this->assertCount(4, $result);
@@ -65,23 +66,52 @@ class MaterializedPathORMRepositoryTest extends BaseTestCaseORM
         $this->assertEquals('Potatoes', $result[2]->getTitle());
         $this->assertEquals('Vegitables', $result[3]->getTitle());
 
-        // Get direct children from the root
-        $result = $repo->getChildren($root, true, 'title');
+        // Get all children from the root, including it
+        $result = $repo->getChildren($root, false, 'title', 'asc', true);
+
+        $this->assertCount(5, $result);
+        $this->assertEquals('Carrots', $result[0]->getTitle());
+        $this->assertEquals('Food', $result[1]->getTitle());
+        $this->assertEquals('Fruits', $result[2]->getTitle());
+        $this->assertEquals('Potatoes', $result[3]->getTitle());
+        $this->assertEquals('Vegitables', $result[4]->getTitle());
+
+        // Get direct children from the root, NOT including it
+        $result = $repo->getChildren($root, true, 'title', 'asc');
 
         $this->assertCount(2, $result);
         $this->assertEquals('Fruits', $result[0]->getTitle());
         $this->assertEquals('Vegitables', $result[1]->getTitle());
 
+        // Get direct children from the root, including it
+        $result = $repo->getChildren($root, true, 'title', 'asc', true);
+
+        $this->assertCount(3, $result);
+        $this->assertEquals('Food', $result[0]->getTitle());
+        $this->assertEquals('Fruits', $result[1]->getTitle());
+        $this->assertEquals('Vegitables', $result[2]->getTitle());
+
         // Get ALL nodes
         $result = $repo->getChildren(null, false, 'title');
 
-        $this->assertCount(6, $result);
-        $this->assertEquals('Carrots', $result[0]->getTitle());
+        $this->assertCount(9, $result);
+        $this->assertEquals('Best Whisky', $result[0]->getTitle());
+        $this->assertEquals('Carrots', $result[1]->getTitle());
+        $this->assertEquals('Drinks', $result[2]->getTitle());
+        $this->assertEquals('Food', $result[3]->getTitle());
+        $this->assertEquals('Fruits', $result[4]->getTitle());
+        $this->assertEquals('Potatoes', $result[5]->getTitle());
+        $this->assertEquals('Sports', $result[6]->getTitle());
+        $this->assertEquals('Vegitables', $result[7]->getTitle());
+        $this->assertEquals('Whisky', $result[8]->getTitle());
+
+        // Get ALL root nodes
+        $result = $repo->getChildren(null, true, 'title');
+
+        $this->assertCount(3, $result);
+        $this->assertEquals('Drinks', $result[0]->getTitle());
         $this->assertEquals('Food', $result[1]->getTitle());
-        $this->assertEquals('Fruits', $result[2]->getTitle());
-        $this->assertEquals('Potatoes', $result[3]->getTitle());
-        $this->assertEquals('Sports', $result[4]->getTitle());
-        $this->assertEquals('Vegitables', $result[5]->getTitle());
+        $this->assertEquals('Sports', $result[2]->getTitle());
     }
 
     /**
@@ -92,28 +122,51 @@ class MaterializedPathORMRepositoryTest extends BaseTestCaseORM
         $repo = $this->em->getRepository(self::CATEGORY);
         $tree = $repo->getTree();
 
-        $this->assertCount(6, $tree);
-        $this->assertEquals('Food', $tree[0]->getTitle());
-        $this->assertEquals('Fruits', $tree[1]->getTitle());
-        $this->assertEquals('Vegitables', $tree[2]->getTitle());
-        $this->assertEquals('Carrots', $tree[3]->getTitle());
-        $this->assertEquals('Potatoes', $tree[4]->getTitle());
-        $this->assertEquals('Sports', $tree[5]->getTitle());
+        $this->assertCount(9, $tree);
+        $this->assertEquals('Drinks', $tree[0]->getTitle());
+        $this->assertEquals('Whisky', $tree[1]->getTitle());
+        $this->assertEquals('Best Whisky', $tree[2]->getTitle());
+        $this->assertEquals('Food', $tree[3]->getTitle());
+        $this->assertEquals('Fruits', $tree[4]->getTitle());
+        $this->assertEquals('Vegitables', $tree[5]->getTitle());
+        $this->assertEquals('Carrots', $tree[6]->getTitle());
+        $this->assertEquals('Potatoes', $tree[7]->getTitle());
+        $this->assertEquals('Sports', $tree[8]->getTitle());
+
+        // Get tree from a specific root node
+        $roots = $repo->getRootNodes();
+        $tree = $repo->getTree($roots[0]);
+
+        $this->assertCount(3, $tree);
+        $this->assertEquals('Drinks', $tree[0]->getTitle());
+        $this->assertEquals('Whisky', $tree[1]->getTitle());
+        $this->assertEquals('Best Whisky', $tree[2]->getTitle());
     }
 
     public function testBuildTreeMethod()
     {
+        /** @var $repo \Gedmo\Tree\Document\MongoDB\Repository\MaterializedPathRepository */
         $repo = $this->em->getRepository(self::CATEGORY);
         $tree = $repo->childrenHierarchy();
 
-        $vegitables = $tree[0]['__children'][1];
-
-        $this->assertEquals('Food', $tree[0]['title']);
-        $this->assertEquals('Fruits', $tree[0]['__children'][0]['title']);
-        $this->assertEquals('Vegitables', $tree[0]['__children'][1]['title']);
-        $this->assertEquals('Carrots', $vegitables['__children'][0]['title']);
-        $this->assertEquals('Potatoes', $vegitables['__children'][1]['title']);
-        $this->assertEquals('Sports', $tree[1]['title']);
+        $this->assertEquals('Drinks', $tree[0]['title']);
+        $this->assertEquals('Whisky', $tree[0]['__children'][0]['title']);
+        $this->assertEquals('Best Whisky', $tree[0]['__children'][0]['__children'][0]['title']);
+        $vegitablesChildren = $tree[1]['__children'][1]['__children'];
+        $this->assertEquals('Food', $tree[1]['title']);
+        $this->assertEquals('Fruits', $tree[1]['__children'][0]['title']);
+        $this->assertEquals('Vegitables', $tree[1]['__children'][1]['title']);
+        $this->assertEquals('Carrots', $vegitablesChildren[0]['title']);
+        $this->assertEquals('Potatoes', $vegitablesChildren[1]['title']);
+        $this->assertEquals('Sports', $tree[2]['title']);
+
+        // Tree of one specific root
+        $roots = $repo->getRootNodes();
+        $tree = $repo->childrenHierarchy($roots[0]);
+
+        $this->assertEquals('Drinks', $tree[0]['title']);
+        $this->assertEquals('Whisky', $tree[0]['__children'][0]['title']);
+        $this->assertEquals('Best Whisky', $tree[0]['__children'][0]['__children'][0]['title']);
     }
 
     protected function getUsedEntityFixtures()
@@ -153,12 +206,27 @@ class MaterializedPathORMRepositoryTest extends BaseTestCaseORM
         $potatoes->setTitle("Potatoes");
         $potatoes->setParent($child2);
 
+        $drinks = $this->createCategory();
+        $drinks->setTitle('Drinks');
+
+        $whisky = $this->createCategory();
+        $whisky->setTitle('Whisky');
+        $whisky->setParent($drinks);
+
+        $bestWhisky = $this->createCategory();
+        $bestWhisky->setTitle('Best Whisky');
+        $bestWhisky->setParent($whisky);
+
         $this->em->persist($root);
         $this->em->persist($root2);
         $this->em->persist($child);
         $this->em->persist($child2);
         $this->em->persist($childsChild);
         $this->em->persist($potatoes);
+        $this->em->persist($drinks);
+        $this->em->persist($whisky);
+        $this->em->persist($bestWhisky);
+
         $this->em->flush();
     }
 }