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 <dave@hobodave.com> |
---|
14 | * @copyright Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/) |
---|
15 | * @license http://hobodave.com/license.txt New BSD License |
---|
16 | */ |
---|
17 | |
---|
18 | namespace Doctrine\ORM\Tools\Pagination; |
---|
19 | |
---|
20 | use Doctrine\ORM\Query\AST\ArithmeticExpression, |
---|
21 | Doctrine\ORM\Query\AST\SimpleArithmeticExpression, |
---|
22 | Doctrine\ORM\Query\TreeWalkerAdapter, |
---|
23 | Doctrine\ORM\Query\AST\SelectStatement, |
---|
24 | Doctrine\ORM\Query\AST\PathExpression, |
---|
25 | Doctrine\ORM\Query\AST\InExpression, |
---|
26 | Doctrine\ORM\Query\AST\NullComparisonExpression, |
---|
27 | Doctrine\ORM\Query\AST\InputParameter, |
---|
28 | Doctrine\ORM\Query\AST\ConditionalPrimary, |
---|
29 | Doctrine\ORM\Query\AST\ConditionalTerm, |
---|
30 | Doctrine\ORM\Query\AST\ConditionalExpression, |
---|
31 | Doctrine\ORM\Query\AST\ConditionalFactor, |
---|
32 | 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 <dave@hobodave.com> |
---|
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 | * @return void |
---|
68 | */ |
---|
69 | public function walkSelectStatement(SelectStatement $AST) |
---|
70 | { |
---|
71 | $rootComponents = array(); |
---|
72 | foreach ($this->_getQueryComponents() AS $dqlAlias => $qComp) { |
---|
73 | $isParent = array_key_exists('parent', $qComp) |
---|
74 | && $qComp['parent'] === null |
---|
75 | && $qComp['nestingLevel'] == 0 |
---|
76 | ; |
---|
77 | if ($isParent) { |
---|
78 | $rootComponents[] = array($dqlAlias => $qComp); |
---|
79 | } |
---|
80 | } |
---|
81 | if (count($rootComponents) > 1) { |
---|
82 | throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); |
---|
83 | } |
---|
84 | $root = reset($rootComponents); |
---|
85 | $parentName = key($root); |
---|
86 | $parent = current($root); |
---|
87 | |
---|
88 | $pathExpression = new PathExpression( |
---|
89 | PathExpression::TYPE_STATE_FIELD, $parentName, $parent['metadata']->getSingleIdentifierFieldName() |
---|
90 | ); |
---|
91 | $pathExpression->type = PathExpression::TYPE_STATE_FIELD; |
---|
92 | |
---|
93 | $count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT); |
---|
94 | |
---|
95 | if ($count > 0) { |
---|
96 | $arithmeticExpression = new ArithmeticExpression(); |
---|
97 | $arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression( |
---|
98 | array($pathExpression) |
---|
99 | ); |
---|
100 | $expression = new InExpression($arithmeticExpression); |
---|
101 | $ns = self::PAGINATOR_ID_ALIAS; |
---|
102 | |
---|
103 | for ($i = 1; $i <= $count; $i++) { |
---|
104 | $expression->literals[] = new InputParameter(":{$ns}_$i"); |
---|
105 | } |
---|
106 | } else { |
---|
107 | $expression = new NullComparisonExpression($pathExpression); |
---|
108 | $expression->not = false; |
---|
109 | } |
---|
110 | |
---|
111 | $conditionalPrimary = new ConditionalPrimary; |
---|
112 | $conditionalPrimary->simpleConditionalExpression = $expression; |
---|
113 | if ($AST->whereClause) { |
---|
114 | if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) { |
---|
115 | $AST->whereClause->conditionalExpression->conditionalFactors[] = $conditionalPrimary; |
---|
116 | } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) { |
---|
117 | $AST->whereClause->conditionalExpression = new ConditionalExpression(array( |
---|
118 | new ConditionalTerm(array( |
---|
119 | $AST->whereClause->conditionalExpression, |
---|
120 | $conditionalPrimary |
---|
121 | )) |
---|
122 | )); |
---|
123 | } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression) { |
---|
124 | $tmpPrimary = new ConditionalPrimary; |
---|
125 | $tmpPrimary->conditionalExpression = $AST->whereClause->conditionalExpression; |
---|
126 | $AST->whereClause->conditionalExpression = new ConditionalTerm(array( |
---|
127 | $tmpPrimary, |
---|
128 | $conditionalPrimary |
---|
129 | )); |
---|
130 | } |
---|
131 | } else { |
---|
132 | $AST->whereClause = new WhereClause( |
---|
133 | new ConditionalExpression(array( |
---|
134 | new ConditionalTerm(array( |
---|
135 | $conditionalPrimary |
---|
136 | )) |
---|
137 | )) |
---|
138 | ); |
---|
139 | } |
---|
140 | } |
---|
141 | } |
---|
142 | |
---|