118 lines
3.2 KiB
PHP
118 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace lib\Core\Utils;
|
|
|
|
class Pagination
|
|
{
|
|
public int $currentPage;
|
|
public int $perPage;
|
|
public int $totalItems;
|
|
public int $totalPages;
|
|
public int $groupSize = 10;
|
|
public int $start;
|
|
public int $end;
|
|
|
|
public function __construct(int $totalItems, int $currentPage = 1, int $perPage = 10)
|
|
{
|
|
$this->totalItems = $totalItems;
|
|
$this->perPage = $perPage;
|
|
$this->currentPage = max(1, $currentPage);
|
|
$this->totalPages = (int)ceil($totalItems / $perPage);
|
|
$this->start = ($this->currentPage - 1) * $perPage;
|
|
$this->end = min($this->start + $perPage, $totalItems);
|
|
$this->groupSize = intval(APP_VIEW_LIST_PAGINATION_GROUPSIZE);
|
|
}
|
|
|
|
public function hasPrevious(): bool
|
|
{
|
|
return $this->currentPage > 1;
|
|
}
|
|
|
|
public function hasNext(): bool
|
|
{
|
|
return $this->currentPage < $this->totalPages;
|
|
}
|
|
|
|
public function previousPage(): int
|
|
{
|
|
return max(1, $this->currentPage - 1);
|
|
}
|
|
|
|
public function nextPage(): int
|
|
{
|
|
return min($this->totalPages, $this->currentPage + 1);
|
|
}
|
|
|
|
public function getOffset(): int
|
|
{
|
|
return $this->start;
|
|
}
|
|
|
|
public function getLimit(): int
|
|
{
|
|
return $this->perPage;
|
|
}
|
|
|
|
public function toArray(): array
|
|
{
|
|
return [
|
|
'current_page' => $this->currentPage,
|
|
'per_page' => $this->perPage,
|
|
'total_items' => $this->totalItems,
|
|
'total_pages' => $this->totalPages,
|
|
'has_previous' => $this->hasPrevious(),
|
|
'has_next' => $this->hasNext(),
|
|
'previous_page' => $this->previousPage(),
|
|
'next_page' => $this->nextPage(),
|
|
'offset' => $this->getOffset(),
|
|
'limit' => $this->getLimit(),
|
|
];
|
|
}
|
|
|
|
public function render(string $baseUrl = '', array $query = []): string
|
|
{
|
|
if ($this->totalPages <= 1) {
|
|
return '';
|
|
}
|
|
|
|
$html = '<nav><ul class="pagination">';
|
|
$currentGroup = (int)floor(($this->currentPage - 1) / $this->groupSize);
|
|
$startPage = $currentGroup * $this->groupSize + 1;
|
|
$endPage = min($startPage + $this->groupSize - 1, $this->totalPages);
|
|
|
|
// << 그룹 이전
|
|
if ($startPage > 1) {
|
|
$prevGroupPage = max(1, $startPage - 1);
|
|
$html .= $this->pageLink($prevGroupPage, '«', $baseUrl, $query);
|
|
} else {
|
|
$html .= '<li class="page-item disabled"><span class="page-link">«</span></li>';
|
|
}
|
|
|
|
// 페이지 번호들
|
|
for ($i = $startPage; $i <= $endPage; $i++) {
|
|
if ($i === $this->currentPage) {
|
|
$html .= '<li class="page-item active"><span class="page-link">' . $i . '</span></li>';
|
|
} else {
|
|
$html .= $this->pageLink($i, (string)$i, $baseUrl, $query);
|
|
}
|
|
}
|
|
|
|
// >> 그룹 다음
|
|
if ($endPage < $this->totalPages) {
|
|
$nextGroupPage = $endPage + 1;
|
|
$html .= $this->pageLink($nextGroupPage, '»', $baseUrl, $query);
|
|
} else {
|
|
$html .= '<li class="page-item disabled"><span class="page-link">»</span></li>';
|
|
}
|
|
|
|
$html .= '</ul></nav>';
|
|
return $html;
|
|
}
|
|
private function pageLink(int $page, string $label, string $baseUrl, array $query): string
|
|
{
|
|
$query['curPage'] = $page;
|
|
$url = $baseUrl . '?' . http_build_query($query);
|
|
return '<li class="page-item"><a class="page-link" href="' . htmlspecialchars($url) . '">' . $label . '</a></li>';
|
|
}
|
|
}
|