244 lines
5.1 KiB
PHP

<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Pagination;
use RuntimeException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Standard paginator class.
*
* Represent a set of paginated pages;
*/
class Paginator implements PaginatorInterface
{
/**
* The number of the current page.
*
* @var int
*/
protected $currentPageNumber;
/**
* the number of items on a single page.
*
* @var int
*/
protected $itemPerPage;
/**
* the key in the GET parameter to indicate the number of item per page.
*
* @var string
*/
protected $itemPerPageKey;
/**
* the key in the GET parameter to indicate the page number in
* generated routes.
*
* @var string
*/
protected $pageKey;
/**
* the route of the pages.
*
* @var string
*/
protected $route;
/**
* the parameters of the route.
*
* @var string[]
*/
protected $routeParameters;
/**
* The number of total items.
*
* @var int
*/
protected $totalItems;
/**
* the generator for url.
*
* @var UrlGeneratorInterface
*/
protected $urlGenerator;
public function __construct(
$totalItems,
$itemPerPage,
$currentPageNumber,
$route,
array $routeParameters,
UrlGeneratorInterface $urlGenerator,
$pageKey,
$itemPerPageKey
) {
$this->totalItems = $totalItems;
$this->itemPerPage = $itemPerPage;
$this->currentPageNumber = $currentPageNumber;
$this->route = $route;
$this->routeParameters = $routeParameters;
$this->urlGenerator = $urlGenerator;
$this->pageKey = $pageKey;
$this->itemPerPageKey = $itemPerPageKey;
}
public function count()
{
return $this->countPages();
}
public function countPages()
{
if (0 === $this->itemPerPage) {
return 1;
}
if (0 === $this->totalItems) {
return 1;
}
$nb = floor($this->totalItems / $this->itemPerPage);
if ($this->totalItems % $this->itemPerPage > 0) {
++$nb;
}
return 0 === $nb ? 1 : (int) $nb;
}
/**
* @return \Chill\MainBundle\Pagination\Page
*/
public function getCurrentPage()
{
return $this->getPage($this->currentPageNumber);
}
public function getCurrentPageFirstItemNumber()
{
return $this->getCurrentPage()->getFirstItemNumber();
}
public function getItemsPerPage()
{
return $this->itemPerPage;
}
/**
* @throws RuntimeException if the next page does not exists
*
* @return \Chill\MainBundle\Pagination\Page
*/
public function getNextPage()
{
if (!$this->hasNextPage()) {
throw new RuntimeException('this page has no next page');
}
return $this->getPage($this->currentPageNumber + 1);
}
/**
* @param type $number
*
* @return \Chill\MainBundle\Pagination\Page
*/
public function getPage($number)
{
if (!$this->hasPage($number)) {
throw new RuntimeException("The page with number {$number} does not "
. 'exists');
}
return new Page(
$number,
$this->itemPerPage,
$this->urlGenerator,
$this->route,
array_merge($this->routeParameters, [
$this->pageKey => $number,
$this->itemPerPageKey => $this->itemPerPage,
]),
$this->totalItems
);
}
public function getPagesGenerator()
{
for ($i = 1; $this->countPages() >= $i; ++$i) {
yield $this->getPage($i);
}
}
/**
* @throws RuntimeException if the next page does not exists
*
* @return \Chill\MainBundle\Pagination\Page
*/
public function getPreviousPage()
{
if (!$this->hasPreviousPage()) {
throw new RuntimeException('this page has no previous page');
}
return $this->getPage($this->currentPageNumber - 1);
}
public function getTotalItems()
{
return $this->totalItems;
}
/**
* @return bool
*/
public function hasNextPage()
{
return $this->hasPage($this->currentPageNumber + 1);
}
public function hasPage($number)
{
if (0 === $this->totalItems) {
return 1 === $number;
}
return 0 < $number
&& $this->countPages() >= $number;
}
/**
* @return bool
*/
public function hasPreviousPage()
{
return $this->hasPage($this->currentPageNumber - 1);
}
public function isCurrentPage(PageInterface $page)
{
return $page->getNumber() === $this->currentPageNumber;
}
public function setItemsPerPage($itemPerPage)
{
$this->itemPerPage = $itemPerPage;
}
}