currentPage = max(1, $currentPage); $this->totalItems = max(0, $totalItems); $this->itemsPerPage = max(1, $itemsPerPage); } public function getTotalPages(): int { return (int) ceil($this->totalItems / $this->itemsPerPage); } public function getOffset(): int { return ($this->currentPage - 1) * $this->itemsPerPage; } public function getCurrentPage(): int { return min($this->currentPage, $this->getTotalPages() ?: 1); } public function hasPages(): bool { return $this->getTotalPages() > 1; } public function hasPreviousPage(): bool { return $this->currentPage > 1; } public function hasNextPage(): bool { return $this->currentPage < $this->getTotalPages(); } public function getPreviousPage(): int { return max(1, $this->currentPage - 1); } public function getNextPage(): int { return min($this->getTotalPages(), $this->currentPage + 1); } public function getVisiblePages(): array { $totalPages = $this->getTotalPages(); if ($totalPages <= self::MAX_VISIBLE_PAGES) { return range(1, $totalPages); } $currentPage = $this->getCurrentPage(); $halfVisible = (int) floor(self::MAX_VISIBLE_PAGES / 2); $startPage = max(1, $currentPage - $halfVisible); $endPage = min($totalPages, $currentPage + $halfVisible); if ($currentPage <= $halfVisible) { $endPage = self::MAX_VISIBLE_PAGES; } if ($currentPage > $totalPages - $halfVisible) { $startPage = $totalPages - self::MAX_VISIBLE_PAGES + 1; } return range($startPage, $endPage); } public function getStartItemNumber(): int { if ($this->totalItems === 0) { return 0; } return $this->getOffset() + 1; } public function getEndItemNumber(): int { return min($this->totalItems, $this->getOffset() + $this->itemsPerPage); } public function getItemsPerPage(): int { return $this->itemsPerPage; } }