vendor/bundles/Pagerfanta/Adapter/DoctrineORMAdapter.php
changeset 15 99ad73ef7385
equal deleted inserted replaced
14:fc78844c8a76 15:99ad73ef7385
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of the Pagerfanta package.
       
     5  *
       
     6  * (c) Pablo Díez <pablodip@gmail.com>
       
     7  *
       
     8  * For the full copyright and license information, please view the LICENSE
       
     9  * file that was distributed with this source code.
       
    10  */
       
    11 
       
    12 namespace Pagerfanta\Adapter;
       
    13 
       
    14 use Doctrine\ORM\QueryBuilder;
       
    15 use Doctrine\ORM\Query;
       
    16 use Doctrine\ORM\NoResultException;
       
    17 
       
    18 /**
       
    19  * DoctrineORMAdapter.
       
    20  *
       
    21  * @author Pablo Díez <pablodip@gmail.com>
       
    22  * @author Benjamin Eberlei <kontakt@beberlei.de>
       
    23  *
       
    24  * @api
       
    25  */
       
    26 class DoctrineORMAdapter implements AdapterInterface
       
    27 {
       
    28     /**
       
    29      * @var Query
       
    30      */
       
    31     private $query;
       
    32 
       
    33     private $fetchJoinCollection;
       
    34 
       
    35     /**
       
    36      * Constructor.
       
    37      *
       
    38      * @param Query|QueryBuilder $query               A Doctrine ORM query or query builder.
       
    39      * @param Boolean            $fetchJoinCollection Whether the query joins a collection (false by default).
       
    40      *
       
    41      * @api
       
    42      */
       
    43     public function __construct($query, $fetchJoinCollection = false)
       
    44     {
       
    45         if ($query instanceof QueryBuilder) {
       
    46             $query = $query->getQuery();
       
    47         }
       
    48 
       
    49         $this->query = $query;
       
    50         $this->fetchJoinCollection = (Boolean) $fetchJoinCollection;
       
    51     }
       
    52 
       
    53     /**
       
    54      * Returns the query
       
    55      *
       
    56      * @return Query
       
    57      *
       
    58      * @api
       
    59      */
       
    60     public function getQuery()
       
    61     {
       
    62         return $this->query;
       
    63     }
       
    64 
       
    65     /**
       
    66      * Returns whether the query joins a collection.
       
    67      *
       
    68      * @return Boolean Whether the query joins a collection.
       
    69      */
       
    70     public function getFetchJoinCollection()
       
    71     {
       
    72         return $this->fetchJoinCollection;
       
    73     }
       
    74 
       
    75     /**
       
    76      * {@inheritdoc}
       
    77      */
       
    78     public function getNbResults()
       
    79     {
       
    80         /* @var $countQuery Query */
       
    81         $countQuery = $this->cloneQuery($this->query);
       
    82 
       
    83         $countQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\CountWalker'));
       
    84         $countQuery->setFirstResult(null)->setMaxResults(null);
       
    85 
       
    86         try {
       
    87             $data =  $countQuery->getScalarResult();
       
    88             $data = array_map('current', $data);
       
    89             return array_sum($data);
       
    90         } catch(NoResultException $e) {
       
    91             return 0;
       
    92         }
       
    93     }
       
    94 
       
    95     /**
       
    96      * {@inheritdoc}
       
    97      */
       
    98     public function getSlice($offset, $length)
       
    99     {
       
   100         if ($this->fetchJoinCollection) {
       
   101             $subQuery = $this->cloneQuery($this->query);
       
   102             $subQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\LimitSubqueryWalker'))
       
   103                 ->setFirstResult($offset)
       
   104                 ->setMaxResults($length);
       
   105 
       
   106             $ids = array_map('current', $subQuery->getScalarResult());
       
   107 
       
   108             $whereInQuery = $this->cloneQuery($this->query);
       
   109             // don't do this for an empty id array
       
   110             if (count($ids) > 0) {
       
   111                 $namespace = 'pg_';
       
   112 
       
   113                 $whereInQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\WhereInWalker'));
       
   114                 $whereInQuery->setHint('id.count', count($ids));
       
   115                 $whereInQuery->setHint('pg.ns', $namespace);
       
   116                 $whereInQuery->setFirstResult(null)->setMaxResults(null);
       
   117                 foreach ($ids as $i => $id) {
       
   118                     $i++;
       
   119                     $whereInQuery->setParameter("{$namespace}_{$i}", $id);
       
   120                 }
       
   121             }
       
   122 
       
   123             return $whereInQuery->getResult($this->query->getHydrationMode());
       
   124         }
       
   125 
       
   126         return $this->cloneQuery($this->query)
       
   127             ->setMaxResults($length)
       
   128             ->setFirstResult($offset)
       
   129             ->getResult($this->query->getHydrationMode())
       
   130         ;
       
   131     }
       
   132 
       
   133     /**
       
   134      * Clones a query.
       
   135      *
       
   136      * @param Query $query The query.
       
   137      *
       
   138      * @return Query The cloned query.
       
   139      */
       
   140     private function cloneQuery(Query $query)
       
   141     {
       
   142         /* @var $cloneQuery Query */
       
   143         $cloneQuery = clone $query;
       
   144         $cloneQuery->setParameters($query->getParameters());
       
   145         foreach ($query->getHints() as $name => $value) {
       
   146             $cloneQuery->setHint($name, $value);
       
   147         }
       
   148 
       
   149         return $cloneQuery;
       
   150     }
       
   151 }