1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Doctrine ORM |
4
|
|
|
* |
5
|
|
|
* LICENSE |
6
|
|
|
* |
7
|
|
|
* This source file is subject to the new BSD license that is bundled |
8
|
|
|
* with this package in the file LICENSE. This license can also be viewed |
9
|
|
|
* at http://hobodave.com/license.txt |
10
|
|
|
* |
11
|
|
|
* @category DoctrineExtensions |
12
|
|
|
* @package DoctrineExtensions\Paginate |
13
|
|
|
* @author David Abdemoulaie <[email protected]> |
14
|
|
|
* @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/) |
15
|
|
|
* @license http://hobodave.com/license.txt New BSD License |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
namespace Eccube\Doctrine\ORM\Tools\Pagination; |
19
|
|
|
|
20
|
|
|
use Doctrine\ORM\Query\AST\ArithmeticExpression; |
21
|
|
|
use Doctrine\ORM\Query\AST\SimpleArithmeticExpression; |
22
|
|
|
use Doctrine\ORM\Query\TreeWalkerAdapter; |
23
|
|
|
use Doctrine\ORM\Query\AST\SelectStatement; |
24
|
|
|
use Doctrine\ORM\Query\AST\PathExpression; |
25
|
|
|
use Doctrine\ORM\Query\AST\InExpression; |
26
|
|
|
use Doctrine\ORM\Query\AST\NullComparisonExpression; |
27
|
|
|
use Doctrine\ORM\Query\AST\InputParameter; |
28
|
|
|
use Doctrine\ORM\Query\AST\ConditionalPrimary; |
29
|
|
|
use Doctrine\ORM\Query\AST\ConditionalTerm; |
30
|
|
|
use Doctrine\ORM\Query\AST\ConditionalExpression; |
31
|
|
|
use Doctrine\ORM\Query\AST\ConditionalFactor; |
32
|
|
|
use Doctrine\ORM\Query\AST\WhereClause; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Replaces the whereClause of the AST with a WHERE id IN (:foo_1, :foo_2) equivalent. |
36
|
|
|
* |
37
|
|
|
* @category DoctrineExtensions |
38
|
|
|
* @package DoctrineExtensions\Paginate |
39
|
|
|
* @author David Abdemoulaie <[email protected]> |
40
|
|
|
* @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/) |
41
|
|
|
* @license http://hobodave.com/license.txt New BSD License |
42
|
|
|
*/ |
43
|
|
|
class WhereInWalker extends TreeWalkerAdapter |
44
|
|
|
{ |
45
|
|
|
/** |
46
|
|
|
* ID Count hint name. |
47
|
|
|
*/ |
48
|
|
|
const HINT_PAGINATOR_ID_COUNT = 'doctrine.id.count'; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Primary key alias for query. |
52
|
|
|
*/ |
53
|
|
|
const PAGINATOR_ID_ALIAS = 'dpid'; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Replaces the whereClause in the AST. |
57
|
|
|
* |
58
|
|
|
* Generates a clause equivalent to WHERE IN (:dpid_1, :dpid_2, ...) |
59
|
|
|
* |
60
|
|
|
* The parameter namespace (dpid) is defined by |
61
|
|
|
* the PAGINATOR_ID_ALIAS |
62
|
|
|
* |
63
|
|
|
* The total number of parameters is retrieved from |
64
|
|
|
* the HINT_PAGINATOR_ID_COUNT query hint. |
65
|
|
|
* |
66
|
|
|
* @param SelectStatement $AST |
67
|
|
|
* |
68
|
|
|
* @return void |
69
|
|
|
* |
70
|
|
|
* @throws \RuntimeException |
71
|
|
|
*/ |
72
|
35 |
|
public function walkSelectStatement(SelectStatement $AST) |
73
|
|
|
{ |
74
|
35 |
|
$queryComponents = $this->_getQueryComponents(); |
75
|
|
|
// Get the root entity and alias from the AST fromClause |
76
|
35 |
|
$from = $AST->fromClause->identificationVariableDeclarations; |
77
|
|
|
|
78
|
35 |
|
if (count($from) > 1) { |
79
|
|
|
throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); |
80
|
|
|
} |
81
|
|
|
|
82
|
35 |
|
$fromRoot = reset($from); |
83
|
35 |
|
$rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; |
84
|
35 |
|
$rootClass = $queryComponents[$rootAlias]['metadata']; |
85
|
35 |
|
$identifierFieldName = $rootClass->getSingleIdentifierFieldName(); |
86
|
|
|
|
87
|
35 |
|
$pathType = PathExpression::TYPE_STATE_FIELD; |
88
|
35 |
|
if (isset($rootClass->associationMappings[$identifierFieldName])) { |
89
|
|
|
$pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; |
90
|
|
|
} |
91
|
|
|
|
92
|
35 |
|
$pathExpression = new PathExpression(PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $rootAlias, $identifierFieldName); |
93
|
35 |
|
$pathExpression->type = $pathType; |
94
|
|
|
|
95
|
35 |
|
$count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT); |
96
|
|
|
|
97
|
35 |
|
if ($count > 0) { |
98
|
35 |
|
$arithmeticExpression = new ArithmeticExpression(); |
99
|
35 |
|
$arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression( |
100
|
35 |
|
array($pathExpression) |
101
|
|
|
); |
102
|
35 |
|
$expression = new InExpression($arithmeticExpression); |
103
|
35 |
|
$expression->literals[] = new InputParameter(":" . self::PAGINATOR_ID_ALIAS); |
104
|
|
|
|
105
|
|
|
} else { |
106
|
|
|
$expression = new NullComparisonExpression($pathExpression); |
107
|
|
|
$expression->not = false; |
108
|
|
|
} |
109
|
|
|
|
110
|
35 |
|
$conditionalPrimary = new ConditionalPrimary; |
111
|
35 |
|
$conditionalPrimary->simpleConditionalExpression = $expression; |
112
|
35 |
|
if ($AST->whereClause) { |
113
|
33 |
|
if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) { |
114
|
13 |
|
$AST->whereClause->conditionalExpression->conditionalFactors[] = $conditionalPrimary; |
115
|
20 |
|
} elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) { |
116
|
15 |
|
$AST->whereClause->conditionalExpression = new ConditionalExpression(array( |
117
|
15 |
|
new ConditionalTerm(array( |
118
|
15 |
|
$AST->whereClause->conditionalExpression, |
119
|
15 |
|
$conditionalPrimary |
120
|
|
|
)) |
121
|
|
|
)); |
122
|
5 |
|
} elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression |
123
|
5 |
|
|| $AST->whereClause->conditionalExpression instanceof ConditionalFactor |
124
|
|
|
) { |
125
|
5 |
|
$tmpPrimary = new ConditionalPrimary; |
126
|
5 |
|
$tmpPrimary->conditionalExpression = $AST->whereClause->conditionalExpression; |
|
|
|
|
127
|
5 |
|
$AST->whereClause->conditionalExpression = new ConditionalTerm(array( |
|
|
|
|
128
|
5 |
|
$tmpPrimary, |
129
|
33 |
|
$conditionalPrimary |
130
|
|
|
)); |
131
|
|
|
} |
132
|
|
|
} else { |
133
|
2 |
|
$AST->whereClause = new WhereClause( |
134
|
2 |
|
new ConditionalExpression(array( |
135
|
2 |
|
new ConditionalTerm(array( |
136
|
2 |
|
$conditionalPrimary |
137
|
|
|
)) |
138
|
|
|
)) |
139
|
|
|
); |
140
|
|
|
} |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.