total = $total; $this->perPage = $perPage; $this->currentPage = max(1, $currentPage); $this->path = $path ?: $_SERVER['REQUEST_URI'] ?? ''; $this->query = $query; } /** * Get current page * * @return int */ public function getCurrentPage(): int { return $this->currentPage; } /** * Get items per page * * @return int */ public function getPerPage(): int { return $this->perPage; } /** * Get total items * * @return int */ public function getTotal(): int { return $this->total; } /** * Get last page * * @return int */ public function getLastPage(): int { return max(1, (int) ceil($this->total / $this->perPage)); } /** * Get offset for database query * * @return int */ public function getOffset(): int { return ($this->currentPage - 1) * $this->perPage; } /** * Check if there are more items * * @return bool */ public function hasMorePages(): bool { return $this->currentPage < $this->getLastPage(); } /** * Check if there are previous pages * * @return bool */ public function hasPreviousPages(): bool { return $this->currentPage > 1; } /** * Get URL for a specific page * * @param int $page * @return string */ public function getUrl(int $page): string { $query = $this->query; $query['page'] = $page; $queryString = http_build_query($query); // Remove the existing query string from the path $path = strtok($this->path, '?'); return $path . ($queryString ? '?' . $queryString : ''); } /** * Get previous page URL * * @return string|null */ public function getPreviousPageUrl(): ?string { if (!$this->hasPreviousPages()) { return null; } return $this->getUrl($this->currentPage - 1); } /** * Get next page URL * * @return string|null */ public function getNextPageUrl(): ?string { if (!$this->hasMorePages()) { return null; } return $this->getUrl($this->currentPage + 1); } /** * Get array of page numbers to display * * @param int $onEachSide * @return array */ public function getPageNumbers(int $onEachSide = 3): array { $lastPage = $this->getLastPage(); $currentPage = $this->currentPage; if ($lastPage <= ($onEachSide * 2) + 1) { return range(1, $lastPage); } $pages = []; // First page $pages[] = 1; // Pages before current $start = max(2, $currentPage - $onEachSide); $end = min($lastPage - 1, $currentPage + $onEachSide); if ($start > 2) { $pages[] = '...'; } for ($i = $start; $i <= $end; $i++) { $pages[] = $i; } if ($end < $lastPage - 1) { $pages[] = '...'; } // Last page if ($lastPage > 1) { $pages[] = $lastPage; } return $pages; } /** * Convert paginator to array for template rendering * * @return array */ public function toArray(): array { return [ 'current_page' => $this->getCurrentPage(), 'per_page' => $this->getPerPage(), 'total' => $this->getTotal(), 'last_page' => $this->getLastPage(), 'offset' => $this->getOffset(), 'has_more_pages' => $this->hasMorePages(), 'has_previous_pages' => $this->hasPreviousPages(), 'previous_page_url' => $this->getPreviousPageUrl(), 'next_page_url' => $this->getNextPageUrl(), 'page_numbers' => $this->getPageNumbers(), ]; } }