diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 83d8455f9..fb5a69aa3 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -440,6 +440,11 @@ parameters: count: 1 path: src/Timestampable/Mapping/Driver/Yaml.php + - + message: "#^Call to an undefined static method Doctrine\\\\ORM\\\\Query\\\\SqlWalker\\:\\:getFinalizer\\(\\)\\.$#" + count: 2 + path: src/Tool/ORM/Walker/CompatSqlOutputWalker.php + - message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\ObjectManager\\:\\:getUnitOfWork\\(\\)\\.$#" count: 1 diff --git a/src/SoftDeleteable/Query/TreeWalker/SoftDeleteableWalker.php b/src/SoftDeleteable/Query/TreeWalker/SoftDeleteableWalker.php index 6f8de3ce7..fd417ff6e 100644 --- a/src/SoftDeleteable/Query/TreeWalker/SoftDeleteableWalker.php +++ b/src/SoftDeleteable/Query/TreeWalker/SoftDeleteableWalker.php @@ -18,12 +18,14 @@ use Doctrine\ORM\Query\AST\SelectStatement; use Doctrine\ORM\Query\AST\UpdateStatement; use Doctrine\ORM\Query\Exec\AbstractSqlExecutor; +use Doctrine\ORM\Query\Exec\PreparedExecutorFinalizer; use Doctrine\ORM\Query\Exec\SingleTableDeleteUpdateExecutor; -use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\Exec\SqlFinalizer; use Gedmo\Exception\RuntimeException; use Gedmo\Exception\UnexpectedValueException; use Gedmo\SoftDeleteable\Query\TreeWalker\Exec\MultiTableDeleteExecutor; use Gedmo\SoftDeleteable\SoftDeleteableListener; +use Gedmo\Tool\ORM\Walker\CompatSqlOutputWalker; use Gedmo\Tool\ORM\Walker\SqlWalkerCompat; /** @@ -36,7 +38,7 @@ * * @final since gedmo/doctrine-extensions 3.11 */ -class SoftDeleteableWalker extends SqlWalker +class SoftDeleteableWalker extends CompatSqlOutputWalker { use SqlWalkerCompat; @@ -104,18 +106,38 @@ protected function doGetExecutorWithCompat($statement): AbstractSqlExecutor { switch (true) { case $statement instanceof DeleteStatement: - assert(class_exists($statement->deleteClause->abstractSchemaName)); - - $primaryClass = $this->getEntityManager()->getClassMetadata($statement->deleteClause->abstractSchemaName); + return $this->createDeleteStatementExecutor($statement); + default: + throw new UnexpectedValueException('SoftDeleteable walker should be used only on delete statement'); + } + } - return $primaryClass->isInheritanceTypeJoined() - ? new MultiTableDeleteExecutor($statement, $this, $this->meta, $this->getConnection()->getDatabasePlatform(), $this->configuration) - : new SingleTableDeleteUpdateExecutor($statement, $this); + /** + * @param DeleteStatement|UpdateStatement|SelectStatement $AST + * + * @throws UnexpectedValueException when an unsupported AST statement is given + */ + protected function doGetFinalizerWithCompat($AST): SqlFinalizer + { + switch (true) { + case $AST instanceof DeleteStatement: + return new PreparedExecutorFinalizer($this->createDeleteStatementExecutor($AST)); default: throw new UnexpectedValueException('SoftDeleteable walker should be used only on delete statement'); } } + protected function createDeleteStatementExecutor(DeleteStatement $AST): AbstractSqlExecutor + { + assert(class_exists($AST->deleteClause->abstractSchemaName)); + + $primaryClass = $this->getEntityManager()->getClassMetadata($AST->deleteClause->abstractSchemaName); + + return $primaryClass->isInheritanceTypeJoined() + ? new MultiTableDeleteExecutor($AST, $this, $this->meta, $this->getConnection()->getDatabasePlatform(), $this->configuration) + : new SingleTableDeleteUpdateExecutor($AST, $this); + } + /** * Changes a DELETE clause into an UPDATE clause for a soft-deleteable entity. */ diff --git a/src/Tool/ORM/Walker/CompatSqlOutputWalker.php b/src/Tool/ORM/Walker/CompatSqlOutputWalker.php new file mode 100644 index 000000000..726dadea2 --- /dev/null +++ b/src/Tool/ORM/Walker/CompatSqlOutputWalker.php @@ -0,0 +1,59 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tool\ORM\Walker; + +use Doctrine\ORM\Query\SqlOutputWalker; +use Doctrine\ORM\Query\SqlWalker; + +if (class_exists(SqlOutputWalker::class)) { + if ((new \ReflectionClass(SqlWalker::class))->getMethod('getExecutor')->hasReturnType()) { + /** + * Helper trait to address compatibility issues between ORM 2.x and 3.x. + * + * @internal + */ + abstract class CompatSqlOutputWalker extends SqlOutputWalker + { + use CompatSqlOutputWalkerForOrm3; + } + } else { + /** + * Helper trait to address compatibility issues between ORM 2.x and 3.x. + * + * @internal + */ + abstract class CompatSqlOutputWalker extends SqlOutputWalker + { + use CompatSqlOutputWalkerForOrm2; + } + } +} else { + if ((new \ReflectionClass(SqlWalker::class))->getMethod('getExecutor')->hasReturnType()) { + /** + * Helper trait to address compatibility issues between ORM 2.x and 3.x. + * + * @internal + */ + abstract class CompatSqlOutputWalker extends SqlWalker + { + use CompatSqlOutputWalkerForOrm3; + } + } else { + /** + * Helper trait to address compatibility issues between ORM 2.x and 3.x. + * + * @internal + */ + abstract class CompatSqlOutputWalker extends SqlWalker + { + use CompatSqlOutputWalkerForOrm2; + } + } +} diff --git a/src/Tool/ORM/Walker/CompatSqlOutputWalkerForOrm2.php b/src/Tool/ORM/Walker/CompatSqlOutputWalkerForOrm2.php new file mode 100644 index 000000000..9639aac52 --- /dev/null +++ b/src/Tool/ORM/Walker/CompatSqlOutputWalkerForOrm2.php @@ -0,0 +1,42 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tool\ORM\Walker; + +use Doctrine\ORM\Query\AST\DeleteStatement; +use Doctrine\ORM\Query\AST\SelectStatement; +use Doctrine\ORM\Query\AST\UpdateStatement; +use Doctrine\ORM\Query\Exec\SqlFinalizer; +use Doctrine\ORM\Query\SqlOutputWalker; + +/** + * Helper trait to address compatibility issues between ORM 2.x and 3.x. + * + * @mixin SqlOutputWalker + * + * @internal + */ +trait CompatSqlOutputWalkerForOrm2 +{ + /** + * @param DeleteStatement|UpdateStatement|SelectStatement $AST + */ + public function getFinalizer($AST): SqlFinalizer + { + return $this->doGetFinalizerWithCompat($AST); + } + + /** + * @param DeleteStatement|UpdateStatement|SelectStatement $AST + */ + protected function doGetFinalizerWithCompat($AST): SqlFinalizer + { + return parent::getFinalizer($AST); + } +} diff --git a/src/Tool/ORM/Walker/CompatSqlOutputWalkerForOrm3.php b/src/Tool/ORM/Walker/CompatSqlOutputWalkerForOrm3.php new file mode 100644 index 000000000..52427fa90 --- /dev/null +++ b/src/Tool/ORM/Walker/CompatSqlOutputWalkerForOrm3.php @@ -0,0 +1,39 @@ + http://www.gediminasm.org + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Gedmo\Tool\ORM\Walker; + +use Doctrine\ORM\Query\AST\DeleteStatement; +use Doctrine\ORM\Query\AST\SelectStatement; +use Doctrine\ORM\Query\AST\UpdateStatement; +use Doctrine\ORM\Query\Exec\SqlFinalizer; +use Doctrine\ORM\Query\SqlOutputWalker; + +/** + * Helper trait to address compatibility issues between ORM 2.x and 3.x. + * + * @mixin SqlOutputWalker + * + * @internal + */ +trait CompatSqlOutputWalkerForOrm3 +{ + public function getFinalizer(DeleteStatement|UpdateStatement|SelectStatement $AST): SqlFinalizer + { + return $this->doGetFinalizerWithCompat($AST); + } + + /** + * @param DeleteStatement|UpdateStatement|SelectStatement $AST + */ + protected function doGetFinalizerWithCompat($AST): SqlFinalizer + { + return parent::getFinalizer($AST); + } +} diff --git a/src/Translatable/Query/TreeWalker/TranslationWalker.php b/src/Translatable/Query/TreeWalker/TranslationWalker.php index 4801ad4d1..63a0832da 100644 --- a/src/Translatable/Query/TreeWalker/TranslationWalker.php +++ b/src/Translatable/Query/TreeWalker/TranslationWalker.php @@ -32,8 +32,10 @@ use Doctrine\ORM\Query\AST\WhereClause; use Doctrine\ORM\Query\Exec\AbstractSqlExecutor; use Doctrine\ORM\Query\Exec\SingleSelectExecutor; -use Doctrine\ORM\Query\SqlWalker; +use Doctrine\ORM\Query\Exec\SingleSelectSqlFinalizer; +use Doctrine\ORM\Query\Exec\SqlFinalizer; use Gedmo\Exception\RuntimeException; +use Gedmo\Tool\ORM\Walker\CompatSqlOutputWalker; use Gedmo\Tool\ORM\Walker\SqlWalkerCompat; use Gedmo\Translatable\Hydrator\ORM\ObjectHydrator; use Gedmo\Translatable\Hydrator\ORM\SimpleObjectHydrator; @@ -54,7 +56,7 @@ * * @final since gedmo/doctrine-extensions 3.11 */ -class TranslationWalker extends SqlWalker +class TranslationWalker extends CompatSqlOutputWalker { use SqlWalkerCompat; @@ -141,6 +143,21 @@ protected function doGetExecutorWithCompat($statement): AbstractSqlExecutor return new SingleSelectExecutor($statement, $this); } + /** + * @param DeleteStatement|UpdateStatement|SelectStatement $AST + */ + protected function doGetFinalizerWithCompat($AST): SqlFinalizer + { + // If it's not a Select, the TreeWalker ought to skip it, and just return the parent. + // @see https://github.com/doctrine-extensions/DoctrineExtensions/issues/2013 + if (!$AST instanceof SelectStatement) { + return parent::getFinalizer($AST); + } + $this->prepareTranslatedComponents(); + + return new SingleSelectSqlFinalizer($this->walkSelectStatement($AST)); + } + protected function doWalkSelectStatementWithCompat(SelectStatement $selectStatement): string { $result = parent::walkSelectStatement($selectStatement);