瀏覽代碼

[Tree] Materialized Path (MongoDB): If PathSource is of type string, the identifier is concatenated to at path generation time

comfortablynumb 13 年之前
父節點
當前提交
9816396005

+ 35 - 8
lib/Gedmo/Tree/Strategy/AbstractMaterializedPath.php

@@ -37,6 +37,15 @@ abstract class AbstractMaterializedPath implements Strategy
      */
     protected $scheduledForPathProcess = array();
 
+    /**
+     * Array of objects which were scheduled for path process.
+     * This time, this array contains the objects with their ID
+     * already set
+     *
+     * @var array
+     */
+    protected $scheduledForPathProcessWithIdSet = array();
+
     /**
      * {@inheritdoc}
      */
@@ -60,9 +69,10 @@ abstract class AbstractMaterializedPath implements Strategy
     {
         $meta = $om->getClassMetadata(get_class($node));
         $config = $this->listener->getConfiguration($om, $meta->name);
+        $fieldMapping = $meta->getFieldMapping($config['path_source']);
 
-        if ($meta->isIdentifier($config['path_source'])) {
-            $this->scheduledForPathProcess[spl_object_hash($node)] = node;
+        if ($meta->isIdentifier($config['path_source']) || $fieldMapping['type'] === 'string') {
+            $this->scheduledForPathProcess[spl_object_hash($node)] = $node;
         } else {
             $this->updateNode($om, $node, $ea);
         }
@@ -97,10 +107,20 @@ abstract class AbstractMaterializedPath implements Strategy
      */
     public function processPostPersist($om, $node, AdapterInterface $ea)
     {
-        foreach ($this->scheduledForPathProcess as $node) {
-            $this->updateNode($om, $node, $ea);
+        $oid = spl_object_hash($node);
+
+        if ($this->scheduledForPathProcess && array_key_exists($oid, $this->scheduledForPathProcess)) {
+            $this->scheduledForPathProcessWithIdSet[$oid] = $node;
 
-            unset($this->scheduledForPathProcess[spl_object_hash($node)]);
+            unset($this->scheduledForPathProcess[$oid]);
+
+            if (empty($this->scheduledForPathProcess)) {
+                foreach ($this->scheduledForPathProcessWithIdSet as $oid => $node) {
+                    $this->updateNode($om, $node, $ea);
+
+                    unset($this->scheduledForPathProcessWithIdSet[$oid]);
+                }
+            }
         }
     }
 
@@ -109,7 +129,6 @@ abstract class AbstractMaterializedPath implements Strategy
      */
     public function onFlushEnd($om)
     {
-        $this->scheduledForPathProcess = array();
     }
 
     /**
@@ -162,7 +181,15 @@ abstract class AbstractMaterializedPath implements Strategy
         $pathProp->setAccessible(true);
         $pathSourceProp = $meta->getReflectionProperty($config['path_source']);
         $pathSourceProp->setAccessible(true);
-        $path = $pathSourceProp->getValue($node).$config['path_separator'];
+        $path = $pathSourceProp->getValue($node);
+        $fieldMapping = $meta->getFieldMapping($config['path_source']);
+
+        // If PathSource field is a string, we append the ID to the path
+        if ($fieldMapping['type'] === 'string') {
+            $path .= '-'.$meta->getIdentifierValue($node);
+        }
+
+        $path .= $config['path_separator'];
 
         if ($parent) {
             $changeSet = $uow->isScheduledForUpdate($parent) ? $ea->getObjectChangeSet($uow, $parent) : false;
@@ -174,7 +201,7 @@ abstract class AbstractMaterializedPath implements Strategy
 
             $path = $pathProp->getValue($parent).$path;
         }
-
+        
         $pathProp->setValue($node, $path);
         $changes = array(
             $config['path'] => array(null, $path)

+ 14 - 8
tests/Gedmo/Tree/MaterializedPathODMMongoDBTest.php

@@ -67,10 +67,10 @@ class MaterializedPathODMMongoDBTest extends BaseTestCaseMongoODM
         $this->dm->refresh($category3);
         $this->dm->refresh($category4);
 
-        $this->assertEquals($this->generatePath(array('1')), $category->getPath());
-        $this->assertEquals($this->generatePath(array('1', '2')), $category2->getPath());
-        $this->assertEquals($this->generatePath(array('1', '2', '3')), $category3->getPath());
-        $this->assertEquals($this->generatePath(array('4')), $category4->getPath());
+        $this->assertEquals($this->generatePath(array('1' => $category->getId())), $category->getPath());
+        $this->assertEquals($this->generatePath(array('1' => $category->getId(), '2' => $category2->getId())), $category2->getPath());
+        $this->assertEquals($this->generatePath(array('1' => $category->getId(), '2' => $category2->getId(), '3' => $category3->getId())), $category3->getPath());
+        $this->assertEquals($this->generatePath(array('4' => $category4->getId())), $category4->getPath());
         $this->assertEquals(1, $category->getLevel());
         $this->assertEquals(2, $category2->getLevel());
         $this->assertEquals(3, $category3->getLevel());
@@ -86,9 +86,9 @@ class MaterializedPathODMMongoDBTest extends BaseTestCaseMongoODM
         $this->dm->refresh($category2);
         $this->dm->refresh($category3);
 
-        $this->assertEquals($this->generatePath(array('1')), $category->getPath());
-        $this->assertEquals($this->generatePath(array('2')), $category2->getPath());
-        $this->assertEquals($this->generatePath(array('2', '3')), $category3->getPath());
+        $this->assertEquals($this->generatePath(array('1' => $category->getId())), $category->getPath());
+        $this->assertEquals($this->generatePath(array('2' => $category2->getId())), $category2->getPath());
+        $this->assertEquals($this->generatePath(array('2' => $category2->getId(), '3' => $category3->getId())), $category3->getPath());
         $this->assertEquals(1, $category->getLevel());
         $this->assertEquals(1, $category2->getLevel());
         $this->assertEquals(2, $category3->getLevel());
@@ -116,6 +116,12 @@ class MaterializedPathODMMongoDBTest extends BaseTestCaseMongoODM
 
     public function generatePath(array $sources)
     {
-        return implode($this->config['path_separator'], $sources).$this->config['path_separator'];
+        $path = '';
+
+        foreach ($sources as $p => $id) {
+            $path .= $p.'-'.$id.$this->config['path_separator'];
+        }
+
+        return $path;
     }
 }