diff --git a/src/Pagination/Paginator.php b/src/Pagination/Paginator.php new file mode 100644 index 000000000..c0e8df2ca --- /dev/null +++ b/src/Pagination/Paginator.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace App\Pagination; + +use Doctrine\ORM\QueryBuilder as DoctrineQueryBuilder; +use Doctrine\ORM\Tools\Pagination\CountWalker; +use Doctrine\ORM\Tools\Pagination\Paginator as DoctrinePaginator; + +/** + * @author Javier Eguiluz + */ +class Paginator +{ + private const PAGE_SIZE = 10; + private $currentPage; + private $pageSize; + private $results; + private $numResults; + + public function __construct(DoctrineQueryBuilder $queryBuilder, int $currentPage = 1, int $pageSize = self::PAGE_SIZE) + { + $this->currentPage = max(1, $currentPage); + $this->pageSize = $pageSize; + $firstResult = ($this->currentPage - 1) * $pageSize; + + $query = $queryBuilder + ->setFirstResult($firstResult) + ->setMaxResults($pageSize) + ->getQuery(); + + if (0 === \count($queryBuilder->getDQLPart('join'))) { + $query->setHint(CountWalker::HINT_DISTINCT, false); + } + + $paginator = new DoctrinePaginator($query, true); + $paginator->setUseOutputWalkers(false); + + $this->results = $paginator->getIterator(); + $this->numResults = $paginator->count(); + } + + public function getCurrentPage(): int + { + return $this->currentPage; + } + + public function getLastPage(): int + { + return (int) ceil($this->numResults / $this->pageSize); + } + + public function getPageSize(): int + { + return $this->pageSize; + } + + public function hasPreviousPage(): bool + { + return $this->currentPage > 1; + } + + public function getPreviousPage(): int + { + return max(1, $this->currentPage - 1); + } + + public function hasNextPage(): bool + { + return $this->currentPage < $this->getLastPage(); + } + + public function getNextPage(): int + { + return min($this->getLastPage(), $this->currentPage + 1); + } + + public function hasToPaginate(): bool + { + return $this->numResults > $this->pageSize; + } + + public function getNumResults(): int + { + return $this->numResults; + } + + public function getResults(): ?\Traversable + { + return $this->results; + } +} diff --git a/src/Repository/PostRepository.php b/src/Repository/PostRepository.php index 1fc2252c5..6a60288f6 100644 --- a/src/Repository/PostRepository.php +++ b/src/Repository/PostRepository.php @@ -13,10 +13,9 @@ use App\Entity\Post; use App\Entity\Tag; +use App\Pagination\Paginator; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Common\Persistence\ManagerRegistry; -use Doctrine\ORM\QueryBuilder; -use Doctrine\ORM\Tools\Pagination\Paginator; /** * This custom Doctrine repository contains some methods which are useful when @@ -35,7 +34,7 @@ public function __construct(ManagerRegistry $registry) parent::__construct($registry, Post::class); } - public function findLatest(int $page = 1, Tag $tag = null): array + public function findLatest(int $page = 1, Tag $tag = null): Paginator { $qb = $this->createQueryBuilder('p') ->addSelect('a', 't') @@ -51,7 +50,7 @@ public function findLatest(int $page = 1, Tag $tag = null): array ->setParameter('tag', $tag); } - return $this->createPaginator($qb, $page); + return new Paginator($qb, $page); } /** @@ -101,31 +100,4 @@ private function extractSearchTerms(string $searchQuery): array return 2 <= mb_strlen($term); }); } - - private function createPaginator(QueryBuilder $queryBuilder, int $currentPage, int $pageSize = Post::NUM_ITEMS) - { - $currentPage = $currentPage < 1 ? 1 : $currentPage; - $firstResult = ($currentPage - 1) * $pageSize; - - $query = $queryBuilder - ->setFirstResult($firstResult) - ->setMaxResults($pageSize) - ->getQuery(); - - $paginator = new Paginator($query); - $numResults = $paginator->count(); - $hasPreviousPage = $currentPage > 1; - $hasNextPage = ($currentPage * $pageSize) < $numResults; - - return [ - 'results' => $paginator->getIterator(), - 'currentPage' => $currentPage, - 'hasPreviousPage' => $hasPreviousPage, - 'hasNextPage' => $hasNextPage, - 'previousPage' => $hasPreviousPage ? $currentPage - 1 : null, - 'nextPage' => $hasNextPage ? $currentPage + 1 : null, - 'numPages' => (int) ceil($numResults / $pageSize), - 'haveToPaginate' => $numResults > $pageSize, - ]; - } } diff --git a/templates/blog/index.html.twig b/templates/blog/index.html.twig index 411f80eb7..b4d43cbe9 100644 --- a/templates/blog/index.html.twig +++ b/templates/blog/index.html.twig @@ -24,7 +24,7 @@
{{ 'post.no_posts_found'|trans }}
{% endfor %} - {% if paginator.haveToPaginate %} + {% if paginator.hasToPaginate %}