From ca3e76f8cab064a593a852d7551217b5d8d37003 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Sun, 22 Jan 2012 15:35:31 +0100 Subject: [PATCH] Refactored the ORM pagination to use the native one in 2.2 --- .../Adapter/DoctrineORM/Paginator.php | 156 ++++++++++++++++++ src/Pagerfanta/Adapter/DoctrineORMAdapter.php | 89 ++-------- 2 files changed, 170 insertions(+), 75 deletions(-) create mode 100644 src/Pagerfanta/Adapter/DoctrineORM/Paginator.php diff --git a/src/Pagerfanta/Adapter/DoctrineORM/Paginator.php b/src/Pagerfanta/Adapter/DoctrineORM/Paginator.php new file mode 100644 index 00000000..60777ce6 --- /dev/null +++ b/src/Pagerfanta/Adapter/DoctrineORM/Paginator.php @@ -0,0 +1,156 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Pagerfanta\Adapter\DoctrineORM; + +use Doctrine\ORM\QueryBuilder; +use Doctrine\ORM\Query; +use Doctrine\ORM\NoResultException; + +/** + * DoctrineORM Paginator. + * + * @author Pablo Díez + * @author Benjamin Eberlei + * + * @api + */ +class Paginator implements \Countable, \IteratorAggregate +{ + /** + * @var Query + */ + private $query; + + private $fetchJoinCollection; + + /** + * Constructor. + * + * @param Query|QueryBuilder $query A Doctrine ORM query or query builder. + * @param Boolean $fetchJoinCollection Whether the query joins a collection (true by default). + * + * @api + */ + public function __construct($query, $fetchJoinCollection = true) + { + if ($query instanceof QueryBuilder) { + $query = $query->getQuery(); + } + + $this->query = $query; + $this->fetchJoinCollection = (Boolean) $fetchJoinCollection; + } + + /** + * Returns the query + * + * @return Query + * + * @api + */ + public function getQuery() + { + return $this->query; + } + + /** + * Returns whether the query joins a collection. + * + * @return Boolean Whether the query joins a collection. + */ + public function getFetchJoinCollection() + { + return $this->fetchJoinCollection; + } + + /** + * {@inheritdoc} + */ + public function count() + { + /* @var $countQuery Query */ + $countQuery = $this->cloneQuery($this->query); + + $countQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\CountWalker')); + $countQuery->setFirstResult(null)->setMaxResults(null); + + try { + $data = $countQuery->getScalarResult(); + $data = array_map('current', $data); + return array_sum($data); + } catch(NoResultException $e) { + return 0; + } + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + $offset = $this->query->getFirstResult(); + $length = $this->query->getMaxResults(); + + if ($this->fetchJoinCollection) { + $subQuery = $this->cloneQuery($this->query); + $subQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\LimitSubqueryWalker')) + ->setFirstResult($offset) + ->setMaxResults($length); + + $ids = array_map('current', $subQuery->getScalarResult()); + + $whereInQuery = $this->cloneQuery($this->query); + // don't do this for an empty id array + if (count($ids) > 0) { + $namespace = 'pg_'; + + $whereInQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\WhereInWalker')); + $whereInQuery->setHint('id.count', count($ids)); + $whereInQuery->setHint('pg.ns', $namespace); + $whereInQuery->setFirstResult(null)->setMaxResults(null); + foreach ($ids as $i => $id) { + $i++; + $whereInQuery->setParameter("{$namespace}_{$i}", $id); + } + } + + return new \ArrayIterator($whereInQuery->getResult($this->query->getHydrationMode())); + } + + $result = $this->cloneQuery($this->query) + ->setMaxResults($length) + ->setFirstResult($offset) + ->getResult($this->query->getHydrationMode()) + ; + + return new \ArrayIterator($result); + } + + /** + * Clones a query. + * + * @param Query $query The query. + * + * @return Query The cloned query. + */ + private function cloneQuery(Query $query) + { + /* @var $cloneQuery Query */ + $cloneQuery = clone $query; + $cloneQuery->setParameters($query->getParameters()); + foreach ($query->getHints() as $name => $value) { + $cloneQuery->setHint($name, $value); + } + + return $cloneQuery; + } +} diff --git a/src/Pagerfanta/Adapter/DoctrineORMAdapter.php b/src/Pagerfanta/Adapter/DoctrineORMAdapter.php index bb7dbb7f..40dedf36 100755 --- a/src/Pagerfanta/Adapter/DoctrineORMAdapter.php +++ b/src/Pagerfanta/Adapter/DoctrineORMAdapter.php @@ -11,9 +11,8 @@ namespace Pagerfanta\Adapter; -use Doctrine\ORM\QueryBuilder; -use Doctrine\ORM\Query; -use Doctrine\ORM\NoResultException; +use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator; +use Pagerfanta\Adapter\DoctrineORM\Paginator as LegacyPaginator; /** * DoctrineORMAdapter. @@ -28,26 +27,23 @@ class DoctrineORMAdapter implements AdapterInterface /** * @var Query */ - private $query; - - private $fetchJoinCollection; + private $paginator; /** * Constructor. * - * @param Query|QueryBuilder $query A Doctrine ORM query or query builder. + * @param \Doctrine\ORM\Query|\Doctrine\ORM\QueryBuilder $query A Doctrine ORM query or query builder. * @param Boolean $fetchJoinCollection Whether the query joins a collection (true by default). * * @api */ public function __construct($query, $fetchJoinCollection = true) { - if ($query instanceof QueryBuilder) { - $query = $query->getQuery(); + if (class_exists('Doctrine\ORM\Tools\Pagination\Paginator')) { + $this->paginator = new DoctrinePaginator($query, $fetchJoinCollection); + } else { + $this->paginator = new LegacyPaginator($query, $fetchJoinCollection); } - - $this->query = $query; - $this->fetchJoinCollection = (Boolean) $fetchJoinCollection; } /** @@ -59,7 +55,7 @@ public function __construct($query, $fetchJoinCollection = true) */ public function getQuery() { - return $this->query; + return $this->paginator->getQuery(); } /** @@ -69,7 +65,7 @@ public function getQuery() */ public function getFetchJoinCollection() { - return $this->fetchJoinCollection; + return $this->paginator->getFetchJoinCollection(); } /** @@ -77,19 +73,7 @@ public function getFetchJoinCollection() */ public function getNbResults() { - /* @var $countQuery Query */ - $countQuery = $this->cloneQuery($this->query); - - $countQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\CountWalker')); - $countQuery->setFirstResult(null)->setMaxResults(null); - - try { - $data = $countQuery->getScalarResult(); - $data = array_map('current', $data); - return array_sum($data); - } catch(NoResultException $e) { - return 0; - } + return count($this->paginator); } /** @@ -97,55 +81,10 @@ public function getNbResults() */ public function getSlice($offset, $length) { - if ($this->fetchJoinCollection) { - $subQuery = $this->cloneQuery($this->query); - $subQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\LimitSubqueryWalker')) - ->setFirstResult($offset) - ->setMaxResults($length); - - $ids = array_map('current', $subQuery->getScalarResult()); - - $whereInQuery = $this->cloneQuery($this->query); - // don't do this for an empty id array - if (count($ids) > 0) { - $namespace = 'pg_'; - - $whereInQuery->setHint(Query::HINT_CUSTOM_TREE_WALKERS, array('Pagerfanta\Adapter\DoctrineORM\WhereInWalker')); - $whereInQuery->setHint('id.count', count($ids)); - $whereInQuery->setHint('pg.ns', $namespace); - $whereInQuery->setFirstResult(null)->setMaxResults(null); - foreach ($ids as $i => $id) { - $i++; - $whereInQuery->setParameter("{$namespace}_{$i}", $id); - } - } - - return $whereInQuery->getResult($this->query->getHydrationMode()); - } - - return $this->cloneQuery($this->query) - ->setMaxResults($length) + $this->paginator->getQuery() ->setFirstResult($offset) - ->getResult($this->query->getHydrationMode()) - ; - } - - /** - * Clones a query. - * - * @param Query $query The query. - * - * @return Query The cloned query. - */ - private function cloneQuery(Query $query) - { - /* @var $cloneQuery Query */ - $cloneQuery = clone $query; - $cloneQuery->setParameters($query->getParameters()); - foreach ($query->getHints() as $name => $value) { - $cloneQuery->setHint($name, $value); - } + ->setMaxResults($length); - return $cloneQuery; + return $this->paginator->getIterator(); } }