Jelajahi Sumber

Moved handling of adding/removing tree nodes to onFlush() hook

All job previously done in prePersist() hook is now called in onFlush()
and is called "processScheduledInsertion()". Same for removal.

prePersist and preRemove hooks are still called for compatibility, but
as for now they do nothing both for Nested and Closure Strategy

Added unit test to ensure early persist is working correctly
Illya Klymov 14 tahun lalu
induk
melakukan
9e7cfec838

+ 12 - 3
lib/Gedmo/Tree/Strategy.php

@@ -29,6 +29,15 @@ interface Strategy
      */
     function __construct(TreeListener $listener);
 
+    /**
+     * Operations on tree node insertion
+     *
+     * @param object $om - object manager
+     * @param object $object - node
+     * @return void
+     */
+    function processScheduledInsertion($om, $object);
+
     /**
      * Operations on tree node updates
      *
@@ -39,13 +48,13 @@ interface Strategy
     function processScheduledUpdate($om, $object);
 
     /**
-     * Operations on tree node deletions
+     * Operations on tree node removal
      *
      * @param object $om - object manager
      * @param object $object - node
      * @return void
      */
-    function processScheduledDelete($om, $object);
+    function processPreRemove($om, $object);
 
     /**
      * Operations on tree node persist
@@ -72,4 +81,4 @@ interface Strategy
      * @return void
      */
     function onFlushEnd($om);
-}
+}

+ 16 - 2
lib/Gedmo/Tree/Strategy/ORM/Closure.php

@@ -62,7 +62,21 @@ class Closure implements Strategy
     /**
      * {@inheritdoc}
      */
-    public function processPrePersist($em, $entity)
+    public function processPrePersist($em, $node)
+    {
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function processPreRemove($em, $node)
+    {
+    }
+
+     /**
+     * {@inheritdoc}
+     */
+    public function processScheduledInsertion($em, $entity)
     {
         $this->pendingChildNodeInserts[] = $entity;
 
@@ -330,4 +344,4 @@ class Closure implements Strategy
     public function onFlushEnd($em)
     {
     }
-}
+}

+ 15 - 1
lib/Gedmo/Tree/Strategy/ORM/Nested.php

@@ -207,6 +207,20 @@ class Nested implements Strategy
      * {@inheritdoc}
      */
     public function processPrePersist($em, $node)
+    {
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function processPreRemove($em, $node)
+    {
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function processScheduledInsertion($em, $node)
     {
         $meta = $em->getClassMetadata(get_class($node));
         $config = $this->listener->getConfiguration($em, $meta->name);
@@ -501,4 +515,4 @@ class Nested implements Strategy
             $this->treeEdges[$meta->name] = $edge + 2;
         }
     }
-}
+}

+ 20 - 2
lib/Gedmo/Tree/TreeListener.php

@@ -96,6 +96,15 @@ class TreeListener extends MappedEventSubscriber
         // check all scheduled updates for TreeNodes
         $usedClasses = array();
 
+        foreach ($ea->getScheduledObjectInsertions($uow) as $object) {
+            $meta = $om->getClassMetadata(get_class($object));
+            if ($config = $this->getConfiguration($om, $meta->name)) {
+                $usedClasses[$meta->name] = null;
+                $this->getStrategy($om, $meta->name)->processScheduledInsertion($om, $object);
+                $uow->recomputeSingleEntityChangeSet($meta, $object);
+            }
+        }
+
         foreach ($ea->getScheduledObjectUpdates($uow) as $object) {
             $meta = $om->getClassMetadata(get_class($object));
             if ($config = $this->getConfiguration($om, $meta->name)) {
@@ -103,6 +112,15 @@ class TreeListener extends MappedEventSubscriber
                 $this->getStrategy($om, $meta->name)->processScheduledUpdate($om, $object);
             }
         }
+
+        foreach ($ea->getScheduledObjectDeletions($uow) as $object) {
+            $meta = $om->getClassMetadata(get_class($object));
+            if ($config = $this->getConfiguration($om, $meta->name)) {
+                $usedClasses[$meta->name] = null;
+                $this->getStrategy($om, $meta->name)->processScheduledDelete($om, $object);
+            }
+        }
+
         foreach ($this->getStrategiesUsedForObjects($usedClasses) as $strategy) {
             $strategy->onFlushEnd($om);
         }
@@ -122,7 +140,7 @@ class TreeListener extends MappedEventSubscriber
         $meta = $om->getClassMetadata(get_class($object));
 
         if ($config = $this->getConfiguration($om, $meta->name)) {
-            $this->getStrategy($om, $meta->name)->processScheduledDelete($om, $object);
+            $this->getStrategy($om, $meta->name)->processPreRemove($om, $object);
         }
     }
 
@@ -200,4 +218,4 @@ class TreeListener extends MappedEventSubscriber
         }
         return $strategies;
     }
-}
+}

+ 16 - 0
tests/Gedmo/Tree/TreeTest.php

@@ -153,6 +153,22 @@ class TreeTest extends BaseTestCaseORM
 
         $this->assertEquals($left, 1);
         $this->assertEquals($right, 4);
+
+        // test persisting in any time
+        $yetAnotherChild = new Category();
+        $this->em->persist($yetAnotherChild);
+        $yetAnotherChild->setTitle("yetanotherchild");
+        $yetAnotherChild->setParent($root);
+        $this->em->flush();
+        $this->em->clear();
+
+        $left = $meta->getReflectionProperty('lft')->getValue($yetAnotherChild);
+        $right = $meta->getReflectionProperty('rgt')->getValue($yetAnotherChild);
+        $level = $meta->getReflectionProperty('level')->getValue($yetAnotherChild);
+
+        $this->assertEquals($left, 4);
+        $this->assertEquals($right, 5);
+        $this->assertEquals($level, 1);
     }
 
     protected function getUsedEntityFixtures()