forked from neos/flow-development-collection
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CountWalker.php
75 lines (67 loc) · 2.56 KB
/
CountWalker.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?php
namespace Neos\Flow\Persistence\Doctrine;
/* *
* This script belongs to the Flow framework. *
* *
* This source file is subject to the new BSD license that is bundled *
* with this package in the file License-BSD.txt. *
* */
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Query\AST\AggregateExpression;
use Doctrine\ORM\Query\AST\PathExpression;
use Doctrine\ORM\Query\AST\SelectExpression;
use Doctrine\ORM\Query\AST\SelectStatement;
use Doctrine\ORM\Query\TreeWalkerAdapter;
use Neos\Flow\Annotations as Flow;
/**
* A walker to transform a select query into a count query.
*
* @Flow\Proxy(false)
*/
class CountWalker extends TreeWalkerAdapter
{
/**
* Walks down a SelectStatement AST node, modifying it to retrieve a COUNT
*
* @param SelectStatement $AST
* @return void
*/
public function walkSelectStatement(SelectStatement $AST)
{
$parent = null;
$parentName = null;
foreach ($this->_getQueryComponents() as $dqlAlias => $qComp) {
if ($qComp['parent'] === null && $qComp['nestingLevel'] === 0) {
$parent = $qComp;
$parentName = $dqlAlias;
break;
}
}
if ($this->isDistinctRequired()) {
$AST->selectClause->isDistinct = true;
}
$pathExpression = new PathExpression(
PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION,
$parentName,
$parent['metadata']->getSingleIdentifierFieldName()
);
$pathExpression->type = PathExpression::TYPE_STATE_FIELD;
$AST->selectClause->selectExpressions = [
new SelectExpression(
new AggregateExpression('count', $pathExpression, $AST->selectClause->isDistinct),
null
)
];
// ORDER BY is not needed, only increases query execution through unnecessary sorting.
$AST->orderByClause = null;
}
private function isDistinctRequired(): bool
{
foreach ($this->getQueryComponents() as $queryComponent) {
if (isset($queryComponent['relation']['type']) && $queryComponent['relation']['type'] === ClassMetadataInfo::ONE_TO_MANY) {
return true;
}
}
return false;
}
}