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
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
18 namespace Doctrine\ORM\Tools\Pagination;
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;
35 * Replaces the whereClause of the AST with a WHERE id IN (:foo_1, :foo_2) equivalent
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
43 class WhereInWalker extends TreeWalkerAdapter
48 const HINT_PAGINATOR_ID_COUNT = 'doctrine.id.count';
51 * Primary key alias for query
53 const PAGINATOR_ID_ALIAS = 'dpid';
56 * Replaces the whereClause in the AST
58 * Generates a clause equivalent to WHERE IN (:dpid_1, :dpid_2, ...)
60 * The parameter namespace (dpid) is defined by
61 * the PAGINATOR_ID_ALIAS
63 * The total number of parameters is retrieved from
64 * the HINT_PAGINATOR_ID_COUNT query hint
66 * @param SelectStatement $AST
69 public function walkSelectStatement(SelectStatement $AST)
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
78 $rootComponents[] = array($dqlAlias => $qComp);
81 if (count($rootComponents) > 1) {
82 throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction");
84 $root = reset($rootComponents);
85 $parentName = key($root);
86 $parent = current($root);
87 $identifierFieldName = $parent['metadata']->getSingleIdentifierFieldName();
89 $pathType = PathExpression::TYPE_STATE_FIELD;
90 if (isset($parent['metadata']->associationMappings[$identifierFieldName])) {
91 $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION;
94 $pathExpression = new PathExpression(PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $parentName, $identifierFieldName);
95 $pathExpression->type = $pathType;
97 $count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT);
100 $arithmeticExpression = new ArithmeticExpression();
101 $arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression(
102 array($pathExpression)
104 $expression = new InExpression($arithmeticExpression);
105 $ns = self::PAGINATOR_ID_ALIAS;
107 for ($i = 1; $i <= $count; $i++) {
108 $expression->literals[] = new InputParameter(":{$ns}_$i");
111 $expression = new NullComparisonExpression($pathExpression);
112 $expression->not = false;
115 $conditionalPrimary = new ConditionalPrimary;
116 $conditionalPrimary->simpleConditionalExpression = $expression;
117 if ($AST->whereClause) {
118 if ($AST->whereClause->conditionalExpression instanceof ConditionalTerm) {
119 $AST->whereClause->conditionalExpression->conditionalFactors[] = $conditionalPrimary;
120 } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalPrimary) {
121 $AST->whereClause->conditionalExpression = new ConditionalExpression(array(
122 new ConditionalTerm(array(
123 $AST->whereClause->conditionalExpression,
127 } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression
128 || $AST->whereClause->conditionalExpression instanceof ConditionalFactor
130 $tmpPrimary = new ConditionalPrimary;
131 $tmpPrimary->conditionalExpression = $AST->whereClause->conditionalExpression;
132 $AST->whereClause->conditionalExpression = new ConditionalTerm(array(
138 $AST->whereClause = new WhereClause(
139 new ConditionalExpression(array(
140 new ConditionalTerm(array(