self::MAX_PAGE_SIZE->value()) { throw new \DomainException('Page size must be less than or equal to ' . self::MAX_PAGE_SIZE->value()); } } public function from(): int { return $this->from; } public function to(): int { return $this->to; } public function pageSize(): int { return $this->to - $this->from + 1; } public function pageNumber(): int { return (int) ($this->from / $this->pageSize()) + 1; } public static function ofIndexes(int $from, int $to): self { return new self($from, $to); } public static function ofPage(int $pageNumber, int $pageSize): self { if ($pageNumber <= 0) { throw new \DomainException('Page number must be positive and non-zero'); } if ($pageSize <= 0) { throw new \DomainException('Page size must be positive and non-zero'); } $fromIndex = ($pageNumber - 1) * $pageSize; $toIndex = max($pageNumber * $pageSize - 1, 1); return new self($fromIndex, $toIndex); } public static function ofOffsetAndLimit(int $offset, int $limit): self { if ($offset < 0) { throw new \DomainException('Offset must be non-negative'); } if ($limit <= 0) { throw new \DomainException('Limit must be positive and non-zero'); } $fromIndex = $offset; $toIndex = max($offset + $limit - 1, 1); return new self($fromIndex, $toIndex); } public static function firstPage(int $pageSize = 25): self { return self::ofPage(1, $pageSize); } public function __toString(): string { return sprintf('Pagination{from=%d, to=%d}', $this->from, $this->to); } }