summaryrefslogtreecommitdiff
path: root/vendor/doctrine/orm/src/Tools/Pagination/CountWalker.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/doctrine/orm/src/Tools/Pagination/CountWalker.php')
-rw-r--r--vendor/doctrine/orm/src/Tools/Pagination/CountWalker.php68
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
3declare(strict_types=1);
4
5namespace Doctrine\ORM\Tools\Pagination;
6
7use Doctrine\ORM\Query\AST\AggregateExpression;
8use Doctrine\ORM\Query\AST\PathExpression;
9use Doctrine\ORM\Query\AST\SelectExpression;
10use Doctrine\ORM\Query\AST\SelectStatement;
11use Doctrine\ORM\Query\TreeWalkerAdapter;
12use RuntimeException;
13
14use function count;
15use function reset;
16
17/**
18 * Replaces the selectClause of the AST with a COUNT statement.
19 */
20class 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}