Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / orm / lib / Doctrine / ORM / Tools / Pagination / WhereInWalker.php
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         $identifierFieldName = $parent['metadata']->getSingleIdentifierFieldName();
88
89         $pathType = PathExpression::TYPE_STATE_FIELD;
90         if (isset($parent['metadata']->associationMappings[$identifierFieldName])) {
91             $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION;
92         }
93
94         $pathExpression       = new PathExpression(PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $parentName, $identifierFieldName);
95         $pathExpression->type = $pathType;
96
97         $count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT);
98
99         if ($count > 0) {
100             $arithmeticExpression = new ArithmeticExpression();
101             $arithmeticExpression->simpleArithmeticExpression = new SimpleArithmeticExpression(
102                 array($pathExpression)
103             );
104             $expression = new InExpression($arithmeticExpression);
105             $ns = self::PAGINATOR_ID_ALIAS;
106
107             for ($i = 1; $i <= $count; $i++) {
108                 $expression->literals[] = new InputParameter(":{$ns}_$i");
109             }
110         } else {
111             $expression = new NullComparisonExpression($pathExpression);
112             $expression->not = false;
113         }
114
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,
124                         $conditionalPrimary
125                     ))
126                 ));
127             } elseif ($AST->whereClause->conditionalExpression instanceof ConditionalExpression
128                 || $AST->whereClause->conditionalExpression instanceof ConditionalFactor
129             ) {
130                 $tmpPrimary = new ConditionalPrimary;
131                 $tmpPrimary->conditionalExpression = $AST->whereClause->conditionalExpression;
132                 $AST->whereClause->conditionalExpression = new ConditionalTerm(array(
133                     $tmpPrimary,
134                     $conditionalPrimary
135                 ));
136             }
137         } else {
138             $AST->whereClause = new WhereClause(
139                 new ConditionalExpression(array(
140                     new ConditionalTerm(array(
141                         $conditionalPrimary
142                     ))
143                 ))
144             );
145         }
146     }
147 }
148