mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
Add OrderByIdentifierSqlWalker
This commit is contained in:
parent
fe1ef6002b
commit
af5ad175f8
2 changed files with 102 additions and 0 deletions
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Paweł Jędrzejewski
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\CoreBundle\Doctrine\ORM\SqlWalker;
|
||||
|
||||
use Doctrine\ORM\Query\AST\AggregateExpression;
|
||||
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
|
||||
use Doctrine\ORM\Query\AST\OrderByClause;
|
||||
use Doctrine\ORM\Query\AST\OrderByItem;
|
||||
use Doctrine\ORM\Query\AST\PathExpression;
|
||||
use Doctrine\ORM\Query\AST\SelectStatement;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
|
||||
final class OrderByIdentifierSqlWalker extends SqlWalker
|
||||
{
|
||||
public function walkSelectStatement(SelectStatement $ast)
|
||||
{
|
||||
$dqlAlias = $this->getDqlAlias();
|
||||
|
||||
if (null !== $dqlAlias && $this->isOrderByIdentifierAllowed($ast)) {
|
||||
$this->appendOrderByIdentifier($ast, $dqlAlias);
|
||||
}
|
||||
|
||||
return parent::walkSelectStatement($ast);
|
||||
}
|
||||
|
||||
private function appendOrderByIdentifier(SelectStatement $ast, string $dqlAlias): void
|
||||
{
|
||||
$metadata = $this->getMetadataForDqlAlias($dqlAlias);
|
||||
|
||||
$expression = new PathExpression(
|
||||
PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION,
|
||||
$dqlAlias,
|
||||
$metadata->getSingleIdentifierFieldName()
|
||||
);
|
||||
$expression->type = PathExpression::TYPE_STATE_FIELD;
|
||||
|
||||
$orderById = new OrderByItem($expression);
|
||||
$orderById->type = 'ASC';
|
||||
|
||||
if (null === $ast->orderByClause) {
|
||||
$ast->orderByClause = new OrderByClause([$orderById]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$ast->orderByClause->orderByItems[] = $orderById;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://www.doctrine-project.org/projects/doctrine-orm/en/2.13/cookbook/dql-custom-walkers.html#extending-dql-in-doctrine-orm-custom-ast-walkers
|
||||
*/
|
||||
private function getDqlAlias(): ?string
|
||||
{
|
||||
foreach ($this->getQueryComponents() as $dqlAlias => $queryComponent) {
|
||||
if (null === ($queryComponent['parent'] ?? null) && 0 === ($queryComponent['nestingLevel'] ?? 0)) {
|
||||
return $dqlAlias;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function isOrderByIdentifierAllowed(SelectStatement $ast): bool
|
||||
{
|
||||
// false if not sure the identifier is added to the GROUP BY clause
|
||||
if (null !== $ast->groupByClause) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$expression = current($ast->selectClause->selectExpressions)->expression;
|
||||
|
||||
// false if aggregate functions is used
|
||||
return !$expression instanceof AggregateExpression && !$expression instanceof FunctionNode;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ use Doctrine\Inflector\Rules\Substitution;
|
|||
use Doctrine\Inflector\Rules\Substitutions;
|
||||
use Doctrine\Inflector\Rules\Transformations;
|
||||
use Doctrine\Inflector\Rules\Word;
|
||||
use Doctrine\ORM\Query;
|
||||
use Sylius\Bundle\CoreBundle\DependencyInjection\Compiler\BackwardsCompatibility\CancelOrderStateMachineCallbackPass;
|
||||
use Sylius\Bundle\CoreBundle\DependencyInjection\Compiler\BackwardsCompatibility\ResolveShopUserTargetEntityPass;
|
||||
use Sylius\Bundle\CoreBundle\DependencyInjection\Compiler\CircularDependencyBreakingErrorListenerPass;
|
||||
|
|
@ -30,6 +31,7 @@ use Sylius\Bundle\CoreBundle\DependencyInjection\Compiler\LiipImageFiltersPass;
|
|||
use Sylius\Bundle\CoreBundle\DependencyInjection\Compiler\RegisterTaxCalculationStrategiesPass;
|
||||
use Sylius\Bundle\CoreBundle\DependencyInjection\Compiler\RegisterUriBasedSectionResolverPass;
|
||||
use Sylius\Bundle\CoreBundle\DependencyInjection\Compiler\TranslatableEntityLocalePass;
|
||||
use Sylius\Bundle\CoreBundle\Doctrine\ORM\SqlWalker\OrderByIdentifierSqlWalker;
|
||||
use Sylius\Bundle\ResourceBundle\AbstractResourceBundle;
|
||||
use Sylius\Bundle\ResourceBundle\SyliusResourceBundle;
|
||||
use Sylius\Component\Resource\Metadata\Metadata;
|
||||
|
|
@ -48,6 +50,8 @@ final class SyliusCoreBundle extends AbstractResourceBundle
|
|||
{
|
||||
parent::boot();
|
||||
|
||||
$this->setSqlWalker();
|
||||
|
||||
$factory = InflectorFactory::create();
|
||||
$factory->withPluralRules(new Ruleset(
|
||||
new Transformations(),
|
||||
|
|
@ -82,4 +86,16 @@ final class SyliusCoreBundle extends AbstractResourceBundle
|
|||
{
|
||||
return 'Sylius\Component\Core\Model';
|
||||
}
|
||||
|
||||
private function setSqlWalker(): void
|
||||
{
|
||||
$this->container
|
||||
->get('doctrine.orm.entity_manager')
|
||||
->getConfiguration()
|
||||
->setDefaultQueryHint(
|
||||
Query::HINT_CUSTOM_OUTPUT_WALKER,
|
||||
OrderByIdentifierSqlWalker::class
|
||||
)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue