瀏覽代碼

[SoftDeleteable] Fixed problem with entities which are part of an inheritance tree

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

+ 51 - 0
lib/Gedmo/SoftDeleteable/Query/TreeWalker/Exec/MultiTableDeleteExecutor.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace Gedmo\SoftDeleteable\Query\TreeWalker\Exec;
+
+use Doctrine\ORM\Query\Exec\MultiTableDeleteExecutor as BaseMultiTableDeleteExecutor;
+use Doctrine\ORM\Query\AST\Node;
+use Doctrine\ORM\Mapping\ClassMetadataInfo;
+use Doctrine\DBAL\Platforms\AbstractPlatform;
+
+/**
+ * This class is used when a DELETE DQL query is called for entities
+ * that are part of an inheritance tree
+ *
+ * @author Gustavo Falco <comfortablynumb84@gmail.com>
+ * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
+ * @package Gedmo.Query.TreeWalker.Exec
+ * @subpackage MultiTableDeleteExecutor
+ * @link http://www.gediminasm.org
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+class MultiTableDeleteExecutor extends BaseMultiTableDeleteExecutor
+{
+    /**
+     * {@inheritDoc}
+     */
+    public function __construct(Node $AST, $sqlWalker, ClassMetadataInfo $meta, AbstractPlatform $platform, array $config)
+    {
+        parent::__construct($AST, $sqlWalker);
+
+        $reflProp = new \ReflectionProperty(get_class($this), '_sqlStatements');
+        $reflProp->setAccessible(true);
+
+        $sqlStatements = $reflProp->getValue($this);
+
+        foreach ($sqlStatements as $index => $stmt) {
+            $matches = array();
+            preg_match('/DELETE FROM (\w+) .+/', $stmt, $matches);
+
+            if (isset($matches[1]) && $meta->getQuotedTableName($platform) === $matches[1]) {
+                $sqlStatements[$index] = str_replace('DELETE FROM', 'UPDATE', $stmt);;
+                $sqlStatements[$index] = str_replace('WHERE', 'SET '.$config['fieldName'].' = "'.date('Y-m-d H:i:s').'" WHERE', $sqlStatements[$index]);
+            } else {
+                // We have to avoid the removal of registers of child entities of a SoftDeleteable entity
+                unset($sqlStatements[$index]);
+            }
+        }
+
+        $reflProp->setValue($this, $sqlStatements);
+    }
+}

+ 4 - 2
lib/Gedmo/SoftDeleteable/Query/TreeWalker/SoftDeleteableWalker.php

@@ -8,9 +8,9 @@ use Doctrine\ORM\Query\AST\DeleteClause;
 use Doctrine\ORM\Query\AST\UpdateClause;
 use Doctrine\ORM\Query\AST\UpdateItem;
 use Doctrine\ORM\Query\Exec\SingleTableDeleteUpdateExecutor;
-use Doctrine\ORM\Query\Exec\MultiTableDeleteExecutor;
 use Doctrine\ORM\Query\AST\PathExpression;
 use Gedmo\SoftDeleteable\SoftDeleteableListener;
+use Gedmo\SoftDeleteable\Query\TreeWalker\Exec\MultiTableDeleteExecutor;
 
 /**
  * This SqlWalker is needed when you need to use a DELETE DQL query.
@@ -30,6 +30,7 @@ class SoftDeleteableWalker extends SqlWalker
     protected $conn;
     protected $platform;
     protected $listener;
+    protected $configuration;
     protected $alias;
     protected $deletedAtField;
     protected $meta;
@@ -57,7 +58,7 @@ class SoftDeleteableWalker extends SqlWalker
                 $primaryClass = $this->getEntityManager()->getClassMetadata($AST->deleteClause->abstractSchemaName);
 
                 return ($primaryClass->isInheritanceTypeJoined())
-                    ? new MultiTableDeleteExecutor($AST, $this)
+                    ? new MultiTableDeleteExecutor($AST, $this, $this->meta, $this->platform, $this->configuration)
                     : new SingleTableDeleteUpdateExecutor($AST, $this);
             default:
                 throw new \Gedmo\Exception\UnexpectedValueException('SoftDeleteable walker should be used only on delete statement');
@@ -132,6 +133,7 @@ class SoftDeleteableWalker extends SqlWalker
             $meta = $comp['metadata'];
             $config = $this->listener->getConfiguration($em, $meta->name);
             if ($config && isset($config['softDeleteable']) && $config['softDeleteable']) {
+                $this->configuration = $config;
                 $this->deletedAtField = $config['fieldName'];
                 $this->meta = $meta;
             }

+ 3 - 3
tests/Gedmo/SoftDeleteable/SoftDeleteableEntityTest.php

@@ -105,6 +105,7 @@ class SoftDeleteableEntityTest extends BaseTestCaseORM
             \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
             'Gedmo\SoftDeleteable\Query\TreeWalker\SoftDeleteableWalker'
         );
+        
         $query->execute();
 
         $art = $repo->findOneBy(array($field => $value));
@@ -120,7 +121,7 @@ class SoftDeleteableEntityTest extends BaseTestCaseORM
         $this->assertTrue(is_object($art->getDeletedAt()));
         $this->assertTrue($art->getDeletedAt() instanceof \DateTime);
 
-        /*
+
         // Inheritance tree DELETE DQL
         $this->em->getFilters()->enable(self::SOFT_DELETEABLE_FILTER_NAME);
         
@@ -143,7 +144,7 @@ class SoftDeleteableEntityTest extends BaseTestCaseORM
             \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
             'Gedmo\SoftDeleteable\Query\TreeWalker\SoftDeleteableWalker'
         );
-        
+
         $query->execute();
 
         $p = $megaPageRepo->findOneBy(array('title' => 'Page 1'));
@@ -158,7 +159,6 @@ class SoftDeleteableEntityTest extends BaseTestCaseORM
         $this->assertTrue(is_object($p));
         $this->assertTrue(is_object($p->getDeletedAt()));
         $this->assertTrue($p->getDeletedAt() instanceof \DateTime);
-        */
     }
 
     protected function getUsedEntityFixtures()