Rajout de doctrine/orm
[zf2.biz/galerie.git] / vendor / doctrine / orm / lib / Doctrine / ORM / Tools / Pagination / CountWalker.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.txt.
9  * If you did not receive a copy of the license and are unable to
10  * obtain it through the world-wide-web, please send an email
11  * to kontakt@beberlei.de so I can send you a copy immediately.
12  */
13
14 namespace Doctrine\ORM\Tools\Pagination;
15
16 use Doctrine\ORM\Query\TreeWalkerAdapter,
17     Doctrine\ORM\Query\AST\SelectStatement,
18     Doctrine\ORM\Query\AST\SelectExpression,
19     Doctrine\ORM\Query\AST\PathExpression,
20     Doctrine\ORM\Query\AST\AggregateExpression;
21
22 /**
23  * Replaces the selectClause of the AST with a COUNT statement
24  *
25  * @category    DoctrineExtensions
26  * @package     DoctrineExtensions\Paginate
27  * @author      David Abdemoulaie <dave@hobodave.com>
28  * @copyright   Copyright (c) 2010 David Abdemoulaie (http://hobodave.com/)
29  * @license     http://hobodave.com/license.txt New BSD License
30  */
31 class CountWalker extends TreeWalkerAdapter
32 {
33     /**
34      * Distinct mode hint name
35      */
36     const HINT_DISTINCT = 'doctrine_paginator.distinct';
37
38     /**
39      * Walks down a SelectStatement AST node, modifying it to retrieve a COUNT
40      *
41      * @param SelectStatement $AST
42      * @return void
43      */
44     public function walkSelectStatement(SelectStatement $AST)
45     {
46         if ($AST->havingClause) {
47             throw new \RuntimeException('Cannot count query that uses a HAVING clause. Use the output walkers for pagination');
48         }
49
50         $rootComponents = array();
51         foreach ($this->_getQueryComponents() as $dqlAlias => $qComp) {
52             $isParent = array_key_exists('parent', $qComp)
53                 && $qComp['parent'] === null
54                 && $qComp['nestingLevel'] == 0
55             ;
56             if ($isParent) {
57                 $rootComponents[] = array($dqlAlias => $qComp);
58             }
59         }
60         if (count($rootComponents) > 1) {
61             throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction");
62         }
63         $root                = reset($rootComponents);
64         $parentName          = key($root);
65         $parent              = current($root);
66         $identifierFieldName = $parent['metadata']->getSingleIdentifierFieldName();
67
68         $pathType = PathExpression::TYPE_STATE_FIELD;
69         if (isset($parent['metadata']->associationMappings[$identifierFieldName])) {
70             $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION;
71         }
72
73         $pathExpression = new PathExpression(
74             PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $parentName,
75             $identifierFieldName
76         );
77         $pathExpression->type = $pathType;
78
79         $distinct = $this->_getQuery()->getHint(self::HINT_DISTINCT);
80         $AST->selectClause->selectExpressions = array(
81             new SelectExpression(
82                 new AggregateExpression('count', $pathExpression, $distinct), null
83             )
84         );
85
86         // ORDER BY is not needed, only increases query execution through unnecessary sorting.
87         $AST->orderByClause = null;
88     }
89 }
90