279 lines
6.5 KiB
PHP
279 lines
6.5 KiB
PHP
<?php
|
|
|
|
use KupShop\KupShopBundle\Pager\PagerExtraItem;
|
|
|
|
class Pager implements ArrayAccess
|
|
{
|
|
public const INFINITE_PAGE_COUNT = 999999;
|
|
|
|
protected $pageSideCount = 1;
|
|
protected $pageInsideCount = 3;
|
|
|
|
public $count;
|
|
public $number;
|
|
|
|
public $total;
|
|
public ?int $totalWithExtraItems = null;
|
|
public $onPage;
|
|
|
|
protected $url;
|
|
protected $params = [];
|
|
|
|
protected int $extraItemsOnFirstPage = 0;
|
|
/** @var PagerExtraItem[] */
|
|
protected array $extraItemsOnEachPage = [];
|
|
|
|
public function __construct($pageCount = null, $page = null, $objectCount = null)
|
|
{
|
|
if (!is_null($pageCount)) {
|
|
$this->count = max(1, $pageCount);
|
|
}
|
|
|
|
if (!is_null($page)) {
|
|
$this->number = $page;
|
|
}
|
|
}
|
|
|
|
public function setUrl($url)
|
|
{
|
|
$parts = parse_url($url);
|
|
|
|
$this->url = $parts['path'];
|
|
|
|
if (!empty($parts['query'])) {
|
|
parse_str($parts['query'], $this->params);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* set total number of pages
|
|
* $total = total number of records
|
|
* $this->count = total number of pages
|
|
* */
|
|
public function setTotal($total, $onPage = null)
|
|
{
|
|
// total uz muze mit nejakou hodnotu, napr. pocet banneru v ProductListu (total number of records = bannery + produkty)
|
|
$this->total += $total;
|
|
|
|
if (is_null($this->count)) {
|
|
$extraItems = array_sum($this->getExtraItems());
|
|
$extraItems += $this->getExtraItemsOnNextPages(
|
|
ceil(($this->total + $extraItems) / $this->getOnPage())
|
|
);
|
|
|
|
$this->totalWithExtraItems = $this->total + $extraItems;
|
|
$this->count = ceil($this->totalWithExtraItems / $this->getOnPage());
|
|
}
|
|
|
|
if ($onPage) {
|
|
$this->onPage = $onPage;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $onPage
|
|
*
|
|
* @return $this
|
|
*/
|
|
/*
|
|
* set number of records on the page
|
|
* */
|
|
public function setOnPage($onPage)
|
|
{
|
|
$this->onPage = $onPage;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param int $number
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function setPageNumber($number)
|
|
{
|
|
$this->number = max(1, $number);
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param int $pageSideCount
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function setPageSide($pageSideCount)
|
|
{
|
|
$this->pageSideCount = $pageSideCount;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @param int $pageInsideCount
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function setPageInside($pageInsideCount)
|
|
{
|
|
$this->pageInsideCount = $pageInsideCount;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function getUrl($values)
|
|
{
|
|
$params = array_merge($this->params, $values);
|
|
|
|
if (getVal('page', $params, 0) == 1) {
|
|
unset($params['page']);
|
|
}
|
|
|
|
$query = http_build_query($params);
|
|
|
|
return $query ? '?'.$query : '.';
|
|
}
|
|
|
|
public function __get($name)
|
|
{
|
|
if (method_exists($this, $name)) {
|
|
return $this->$name();
|
|
}
|
|
}
|
|
|
|
public function first()
|
|
{
|
|
return $this->insidePagesFrom() > $this->pageSideCount;
|
|
}
|
|
|
|
public function firstDots()
|
|
{
|
|
return $this->insidePagesFrom() > $this->pageSideCount + 1;
|
|
}
|
|
|
|
public function last()
|
|
{
|
|
return $this->insidePagesTo() < ($this->count - $this->pageSideCount + 1);
|
|
}
|
|
|
|
public function lastDots()
|
|
{
|
|
return $this->insidePagesTo() < $this->count - $this->pageSideCount;
|
|
}
|
|
|
|
public function insidePagesFrom()
|
|
{
|
|
return max(1, $this->number - $this->pageInsideCount);
|
|
}
|
|
|
|
public function insidePagesTo()
|
|
{
|
|
return min($this->count, $this->number + $this->pageInsideCount);
|
|
}
|
|
|
|
public function to()
|
|
{
|
|
return min($this->number * $this->getOnPage() - 1, $this->total ?: self::INFINITE_PAGE_COUNT);
|
|
}
|
|
|
|
public function from()
|
|
{
|
|
return ($this->number - 1) * $this->getOnPage();
|
|
}
|
|
|
|
public function isInfinite(): bool
|
|
{
|
|
return $this->count === self::INFINITE_PAGE_COUNT;
|
|
}
|
|
|
|
public function getSpec()
|
|
{
|
|
return function (Query\QueryBuilder $qb) {
|
|
[$extraItemsOnThisPage, $extraItemsOnPreviousPages] = $this->getExtraItems();
|
|
|
|
$onPage = $this->getOnPage() - $extraItemsOnThisPage;
|
|
$from = max(0, $this->from() - $extraItemsOnPreviousPages);
|
|
|
|
$qb->setMaxResults($onPage)
|
|
->setFirstResult($from);
|
|
|
|
return null;
|
|
};
|
|
}
|
|
|
|
public function addExtraItems(PagerExtraItem $onEachPage): self
|
|
{
|
|
$this->extraItemsOnEachPage[] = $onEachPage;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the extra items for the current and previous pages.
|
|
*
|
|
* @return array{onThisPage: int, onPreviousPages: int}
|
|
*/
|
|
public function getExtraItems(): array
|
|
{
|
|
$extraItemsOnPreviousPages = 0;
|
|
$extraItemsOnThisPage = 0;
|
|
|
|
foreach ($this->extraItemsOnEachPage as $extraItem) {
|
|
$extraItemsOnPreviousPages += min($extraItem->countOnPage * ($this->number - 1), $extraItem->getMax());
|
|
$extraItemsOnThisPage += min($extraItem->countOnPage, max($extraItem->getMax() - $extraItemsOnPreviousPages, 0));
|
|
}
|
|
|
|
return [$extraItemsOnThisPage, $extraItemsOnPreviousPages];
|
|
}
|
|
|
|
/**
|
|
* Get the extra items for the next pages when total pages count is already known.
|
|
*/
|
|
private function getExtraItemsOnNextPages(int $totalPages): int
|
|
{
|
|
$extraItemsOnNextPages = 0;
|
|
|
|
foreach ($this->extraItemsOnEachPage as $extraItem) {
|
|
$extraItemsOnNextPages += min(($totalPages - $this->number) * $extraItem->countOnPage, max($extraItem->getMax() - ($extraItem->countOnPage * $this->number), 0));
|
|
}
|
|
|
|
return $extraItemsOnNextPages;
|
|
}
|
|
|
|
/**
|
|
* Implements ArrayAccess interface.
|
|
*/
|
|
public function offsetSet($offset, $value): void
|
|
{
|
|
$this->{$offset} = $value;
|
|
}
|
|
|
|
public function offsetExists($offset): bool
|
|
{
|
|
return isset($this->{$offset});
|
|
}
|
|
|
|
public function offsetUnset($offset): void
|
|
{
|
|
unset($this->{$offset});
|
|
}
|
|
|
|
public function offsetGet($offset): mixed
|
|
{
|
|
if (method_exists($this, $offset)) {
|
|
return $this->$offset();
|
|
}
|
|
|
|
return isset($this->{$offset}) ? $this->{$offset} : null;
|
|
}
|
|
|
|
public function getOnPage()
|
|
{
|
|
if (empty($this->onPage)) {
|
|
return 30;
|
|
}
|
|
|
|
return $this->onPage;
|
|
}
|
|
}
|