mirror of
https://codeberg.org/vlw/scaffold.git
synced 2025-11-05 06:02:42 +01:00
144 lines
3.2 KiB
PHP
144 lines
3.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Read the documentation at:
|
|
* https://codeberg.org/vlw/scaffold/docs/Database/Paginate.md
|
|
*/
|
|
|
|
namespace vlw\Scaffold\Helpers;
|
|
|
|
class Paginate {
|
|
public const KEY = "p";
|
|
public const DEFAULT_RANGE = 3;
|
|
public const DEFAULT_PAGE_SIZE = 25;
|
|
|
|
/**
|
|
* Start a new Paginate instance
|
|
*
|
|
* @param int $total Total amount of items to paginate
|
|
* @param ?int $size Amount of items to display on each page
|
|
* @param ?int $current Index of current page
|
|
*/
|
|
public function __construct(
|
|
public int $total = 0,
|
|
public ?int $size = null,
|
|
public ?int $current = null
|
|
) {
|
|
if ($this->current === null) {
|
|
// Parse current page from search parameters
|
|
$this->current = array_key_exists($this->key, $_GET) ? $this->clamp((int) $_GET[$this->key]) : 0;
|
|
}
|
|
|
|
if ($this->size === null) {
|
|
$this->size = self::DEFAULT_PAGE_SIZE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Search parameter to use as key for page number
|
|
*/
|
|
public string $key = "p";
|
|
|
|
/**
|
|
* Get current database offset
|
|
*
|
|
* @return int Database offset of first item on current page
|
|
*/
|
|
public int $offset {
|
|
get => max(0, $this->current * $this->size);
|
|
}
|
|
|
|
/**
|
|
* Get total amount of pages
|
|
*
|
|
* @return int Total number of pages
|
|
*/
|
|
public int $pages {
|
|
get => ceil($this->total / $this->size);
|
|
}
|
|
|
|
/**
|
|
* Returns true if a previous page exists
|
|
*
|
|
* @return bool Previous page exists
|
|
*/
|
|
public bool $previous {
|
|
get => $this->current > 0;
|
|
}
|
|
|
|
/**
|
|
* True if a next page exists
|
|
*
|
|
* @return bool Next page exists
|
|
*/
|
|
public bool $next {
|
|
get => $this->current + 1 < $this->pages;
|
|
}
|
|
|
|
/**
|
|
* Get pages witin ±range from current page
|
|
*
|
|
* @param ?int $range Desired range from current page to return
|
|
* @return array<int> Indecies of pages within the desired range
|
|
*/
|
|
public function range(?int $range = self::DEFAULT_RANGE): array {
|
|
$start = max(1, $this->current - max(0, $range - 2));
|
|
$end = min($this->pages, $this->current + $range);
|
|
|
|
$range = [];
|
|
|
|
for ($i = $start; $i <= $end; $i++) {
|
|
$range[] = $i;
|
|
}
|
|
|
|
return $range;
|
|
}
|
|
|
|
/**
|
|
* Returns a url to a page by index
|
|
*
|
|
* @param int $page Page index
|
|
* @return string Search parameters to the target page
|
|
*/
|
|
public function idx(int $page): string {
|
|
return $this->url($page - 1);
|
|
}
|
|
|
|
/**
|
|
* Returns a url to the previous page
|
|
*
|
|
* @return string Search parameters to the previous page
|
|
*/
|
|
public function previous(): string {
|
|
return $this->url($this->current - 1);
|
|
}
|
|
|
|
/**
|
|
* Returns a url to the next page
|
|
*
|
|
* @return string Search parameters to the next page
|
|
*/
|
|
public function next(): string {
|
|
return $this->url($this->current + 1);
|
|
}
|
|
|
|
/**
|
|
* Clamp page within range of all pages
|
|
*
|
|
* @param int $page Page index
|
|
* @return int Clamped page index
|
|
*/
|
|
private function clamp(int $page): int {
|
|
return max(0, min($page, $this->pages - 1));
|
|
}
|
|
|
|
/**
|
|
* Construct search parameters for a page while preserving existing search parameters
|
|
*
|
|
* @param int $page Page index
|
|
* @return string A search parameter to the target page
|
|
*/
|
|
private function url(int $page): string {
|
|
return "?" . http_build_query(array_merge($_GET, [$this->key => $page]));
|
|
}
|
|
}
|