188 lines
4.4 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 Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* Standard paginator class.
*
* Represent a set of paginated pages;
*/
class Paginator implements PaginatorInterface
{
/**
* @param string[] $routeParameters
*/
public function __construct(
/**
* The number of total items.
*/
protected int $totalItems,
/**
* the number of items on a single page.
*/
protected int $itemPerPage,
/**
* The number of the current page.
*/
protected int $currentPageNumber,
/**
* the route of the pages.
*/
protected string $route,
/**
* the parameters of the route.
*/
protected array $routeParameters,
/**
* the generator for url.
*/
protected UrlGeneratorInterface $urlGenerator,
/**
* the key in the GET parameter to indicate the page number in
* generated routes.
*/
protected string $pageKey,
/**
* the key in the GET parameter to indicate the number of item per page.
*/
protected string $itemPerPageKey
) {}
public function count(): int
{
return $this->countPages();
}
public function countPages(): int
{
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;
}
public function getCurrentPage(): Page
{
return $this->getPage($this->currentPageNumber);
}
public function getCurrentPageFirstItemNumber(): int
{
return $this->getCurrentPage()->getFirstItemNumber();
}
public function getItemsPerPage(): int
{
return $this->itemPerPage;
}
/**
* @throws \RuntimeException if the next page does not exists
*/
public function getNextPage(): Page
{
if (!$this->hasNextPage()) {
throw new \RuntimeException('this page has no next page');
}
return $this->getPage($this->currentPageNumber + 1);
}
public function getPage(int $number): Page
{
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(): iterable
{
for ($i = 1; $this->countPages() >= $i; ++$i) {
yield $this->getPage($i);
}
}
/**
* @return Page
*
* @throws \RuntimeException if the next page does not exists
*/
public function getPreviousPage(): PageInterface
{
if (!$this->hasPreviousPage()) {
throw new \RuntimeException('this page has no previous page');
}
return $this->getPage($this->currentPageNumber - 1);
}
public function getTotalItems(): int
{
return $this->totalItems;
}
public function hasNextPage(): bool
{
return $this->hasPage($this->currentPageNumber + 1);
}
public function hasPage($number): bool
{
if (0 === $this->totalItems) {
return 1 === $number;
}
return 0 < $number
&& $this->countPages() >= $number;
}
public function hasPreviousPage(): bool
{
return $this->hasPage($this->currentPageNumber - 1);
}
public function isCurrentPage(PageInterface $page): bool
{
return $page->getNumber() === $this->currentPageNumber;
}
public function setItemsPerPage(int $itemsPerPage)
{
$this->itemPerPage = $itemsPerPage;
}
}