118 lines
2.9 KiB
PHP
118 lines
2.9 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the Symfony package.
|
|
*
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
*
|
|
* 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 <javier.eguiluz@gmail.com>
|
|
*/
|
|
class Paginator
|
|
{
|
|
/**
|
|
* Use constants to define configuration options that rarely change instead
|
|
* of specifying them under parameters section in config/services.yaml file.
|
|
*
|
|
* See https://symfony.com/doc/current/best_practices.html#use-constants-to-define-options-that-rarely-change
|
|
*/
|
|
public const PAGE_SIZE = 10;
|
|
|
|
private $queryBuilder;
|
|
private $currentPage;
|
|
private $pageSize;
|
|
private $results;
|
|
private $numResults;
|
|
|
|
public function __construct(DoctrineQueryBuilder $queryBuilder, int $pageSize = self::PAGE_SIZE)
|
|
{
|
|
$this->queryBuilder = $queryBuilder;
|
|
$this->pageSize = $pageSize;
|
|
}
|
|
|
|
public function paginate(int $page = 1): self
|
|
{
|
|
$this->currentPage = max(1, $page);
|
|
$firstResult = ($this->currentPage - 1) * $this->pageSize;
|
|
|
|
$query = $this->queryBuilder
|
|
->setFirstResult($firstResult)
|
|
->setMaxResults($this->pageSize)
|
|
->getQuery();
|
|
|
|
if (0 === \count($this->queryBuilder->getDQLPart('join'))) {
|
|
$query->setHint(CountWalker::HINT_DISTINCT, false);
|
|
}
|
|
|
|
$paginator = new DoctrinePaginator($query, true);
|
|
|
|
$useOutputWalkers = \count($this->queryBuilder->getDQLPart('having') ?: []) > 0;
|
|
$paginator->setUseOutputWalkers($useOutputWalkers);
|
|
|
|
$this->results = $paginator->getIterator();
|
|
$this->numResults = $paginator->count();
|
|
|
|
return $this;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|