diff options
Diffstat (limited to 'vendor/doctrine/orm/src/Tools/Pagination/CountWalker.php')
-rw-r--r-- | vendor/doctrine/orm/src/Tools/Pagination/CountWalker.php | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/vendor/doctrine/orm/src/Tools/Pagination/CountWalker.php b/vendor/doctrine/orm/src/Tools/Pagination/CountWalker.php new file mode 100644 index 0000000..d212943 --- /dev/null +++ b/vendor/doctrine/orm/src/Tools/Pagination/CountWalker.php | |||
@@ -0,0 +1,68 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\ORM\Tools\Pagination; | ||
6 | |||
7 | use Doctrine\ORM\Query\AST\AggregateExpression; | ||
8 | use Doctrine\ORM\Query\AST\PathExpression; | ||
9 | use Doctrine\ORM\Query\AST\SelectExpression; | ||
10 | use Doctrine\ORM\Query\AST\SelectStatement; | ||
11 | use Doctrine\ORM\Query\TreeWalkerAdapter; | ||
12 | use RuntimeException; | ||
13 | |||
14 | use function count; | ||
15 | use function reset; | ||
16 | |||
17 | /** | ||
18 | * Replaces the selectClause of the AST with a COUNT statement. | ||
19 | */ | ||
20 | class CountWalker extends TreeWalkerAdapter | ||
21 | { | ||
22 | /** | ||
23 | * Distinct mode hint name. | ||
24 | */ | ||
25 | public const HINT_DISTINCT = 'doctrine_paginator.distinct'; | ||
26 | |||
27 | public function walkSelectStatement(SelectStatement $selectStatement): void | ||
28 | { | ||
29 | if ($selectStatement->havingClause) { | ||
30 | throw new RuntimeException('Cannot count query that uses a HAVING clause. Use the output walkers for pagination'); | ||
31 | } | ||
32 | |||
33 | // Get the root entity and alias from the AST fromClause | ||
34 | $from = $selectStatement->fromClause->identificationVariableDeclarations; | ||
35 | |||
36 | if (count($from) > 1) { | ||
37 | throw new RuntimeException('Cannot count query which selects two FROM components, cannot make distinction'); | ||
38 | } | ||
39 | |||
40 | $fromRoot = reset($from); | ||
41 | $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; | ||
42 | $rootClass = $this->getMetadataForDqlAlias($rootAlias); | ||
43 | $identifierFieldName = $rootClass->getSingleIdentifierFieldName(); | ||
44 | |||
45 | $pathType = PathExpression::TYPE_STATE_FIELD; | ||
46 | if (isset($rootClass->associationMappings[$identifierFieldName])) { | ||
47 | $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; | ||
48 | } | ||
49 | |||
50 | $pathExpression = new PathExpression( | ||
51 | PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, | ||
52 | $rootAlias, | ||
53 | $identifierFieldName, | ||
54 | ); | ||
55 | $pathExpression->type = $pathType; | ||
56 | |||
57 | $distinct = $this->_getQuery()->getHint(self::HINT_DISTINCT); | ||
58 | $selectStatement->selectClause->selectExpressions = [ | ||
59 | new SelectExpression( | ||
60 | new AggregateExpression('count', $pathExpression, $distinct), | ||
61 | null, | ||
62 | ), | ||
63 | ]; | ||
64 | |||
65 | // ORDER BY is not needed, only increases query execution through unnecessary sorting. | ||
66 | $selectStatement->orderByClause = null; | ||
67 | } | ||
68 | } | ||