v1.0.0.0
StocketBase
- <?php
- declare(strict_types=1);
- final class Pagination
- {
- public static function currentPage(): int
- {
- $page = (int) ($_GET['page'] ?? 1);
- return $page > 0 ? $page : 1;
- }
- public static function offset(int $page, int $perPage): int
- {
- return ($page - 1) * $perPage;
- }
- public static function totalPages(int $totalItems, int $perPage): int
- {
- if ($perPage <= 0) {
- return 1;
- }
- return max(1, (int) ceil($totalItems / $perPage));
- }
- public static function render(string $style, string $baseUrl, int $currentPage, int $totalPages, array $extraParams = [], string $containerId = ''): string
- {
- if ($totalPages <= 1) {
- return '';
- }
- return match ($style) {
- 'load_more' => self::renderLoadMore($currentPage, $totalPages, $containerId),
- 'infinite_scroll' => self::renderInfiniteScrollMarker($currentPage, $totalPages, $containerId),
- default => self::renderNumbered($baseUrl, $currentPage, $totalPages, $extraParams),
- };
- }
- private static function buildUrl(string $baseUrl, int $page, array $extraParams): string
- {
- $params = $extraParams;
- if ($page > 1) {
- $params['page'] = $page;
- }
- if (empty($params)) {
- return $baseUrl;
- }
- return $baseUrl . '?' . http_build_query($params);
- }
- private static function renderNumbered(string $baseUrl, int $currentPage, int $totalPages, array $extraParams): string
- {
- $html = '<nav class="pagination-numbered" aria-label="Pagination">';
- if ($currentPage > 1) {
- $html .= '<a href="' . htmlspecialchars(self::buildUrl($baseUrl, $currentPage - 1, $extraParams)) . '" class="pagination-link pagination-prev">' . htmlspecialchars(Language::get('pagination_previous', 'Previous')) . '</a>';
- }
- foreach (self::pageWindow($currentPage, $totalPages) as $item) {
- if ($item === null) {
- $html .= '<span class="pagination-ellipsis">…</span>';
- continue;
- }
- $isCurrent = $item === $currentPage;
- $html .= '<a href="' . htmlspecialchars(self::buildUrl($baseUrl, $item, $extraParams)) . '" class="pagination-link' . ($isCurrent ? ' pagination-current' : '') . '"' . ($isCurrent ? ' aria-current="page"' : '') . '>' . $item . '</a>';
- }
- if ($currentPage < $totalPages) {
- $html .= '<a href="' . htmlspecialchars(self::buildUrl($baseUrl, $currentPage + 1, $extraParams)) . '" class="pagination-link pagination-next">' . htmlspecialchars(Language::get('pagination_next', 'Next')) . '</a>';
- }
- $html .= '</nav>';
- return $html;
- }
- private static function pageWindow(int $currentPage, int $totalPages): array
- {
- $window = 2;
- $pages = [];
- for ($i = 1; $i <= $totalPages; $i++) {
- if ($i === 1 || $i === $totalPages || ($i >= $currentPage - $window && $i <= $currentPage + $window)) {
- $pages[] = $i;
- } elseif (!empty($pages) && end($pages) !== null) {
- $pages[] = null;
- }
- }
- return $pages;
- }
- private static function renderLoadMore(int $currentPage, int $totalPages, string $containerId): string
- {
- if ($currentPage >= $totalPages) {
- return '';
- }
- $safeContainerId = htmlspecialchars($containerId);
- return '<div class="pagination-load-more" data-container="' . $safeContainerId . '" data-next-page="' . ($currentPage + 1) . '" data-total-pages="' . $totalPages . '">'
- . '<button type="button" class="unlock-btn pagination-load-more-btn" style="border:none;cursor:pointer;">' . htmlspecialchars(Language::get('pagination_load_more', 'Load more')) . '</button>'
- . '</div>';
- }
- private static function renderInfiniteScrollMarker(int $currentPage, int $totalPages, string $containerId): string
- {
- if ($currentPage >= $totalPages) {
- return '<div class="pagination-end">' . htmlspecialchars(Language::get('pagination_end', 'No more products')) . '</div>';
- }
- $safeContainerId = htmlspecialchars($containerId);
- return '<div class="pagination-infinite-marker" data-container="' . $safeContainerId . '" data-next-page="' . ($currentPage + 1) . '" data-total-pages="' . $totalPages . '"></div>';
- }
- }
-