1: <?php
2:
3: /**
4: * This file is part of the Nette Framework (https://nette.org)
5: * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6: */
7:
8: namespace Nette\Utils;
9:
10: use Nette;
11:
12:
13: /**
14: * Paginating math.
15: *
16: * @property int $page
17: * @property-read int $firstPage
18: * @property-read int|NULL $lastPage
19: * @property int $base
20: * @property-read bool $first
21: * @property-read bool $last
22: * @property-read int|NULL $pageCount
23: * @property int $itemsPerPage
24: * @property int|NULL $itemCount
25: * @property-read int $offset
26: * @property-read int|NULL $countdownOffset
27: * @property-read int|NULL $length
28: */
29: class Paginator extends Nette\Object
30: {
31: /** @var int */
32: private $base = 1;
33:
34: /** @var int */
35: private $itemsPerPage = 1;
36:
37: /** @var int */
38: private $page;
39:
40: /** @var int|NULL */
41: private $itemCount;
42:
43:
44: /**
45: * Sets current page number.
46: * @param int
47: * @return static
48: */
49: public function setPage($page)
50: {
51: $this->page = (int) $page;
52: return $this;
53: }
54:
55:
56: /**
57: * Returns current page number.
58: * @return int
59: */
60: public function getPage()
61: {
62: return $this->base + $this->getPageIndex();
63: }
64:
65:
66: /**
67: * Returns first page number.
68: * @return int
69: */
70: public function getFirstPage()
71: {
72: return $this->base;
73: }
74:
75:
76: /**
77: * Returns last page number.
78: * @return int|NULL
79: */
80: public function getLastPage()
81: {
82: return $this->itemCount === NULL ? NULL : $this->base + max(0, $this->getPageCount() - 1);
83: }
84:
85:
86: /**
87: * Sets first page (base) number.
88: * @param int
89: * @return static
90: */
91: public function setBase($base)
92: {
93: $this->base = (int) $base;
94: return $this;
95: }
96:
97:
98: /**
99: * Returns first page (base) number.
100: * @return int
101: */
102: public function getBase()
103: {
104: return $this->base;
105: }
106:
107:
108: /**
109: * Returns zero-based page number.
110: * @return int
111: */
112: protected function getPageIndex()
113: {
114: $index = max(0, $this->page - $this->base);
115: return $this->itemCount === NULL ? $index : min($index, max(0, $this->getPageCount() - 1));
116: }
117:
118:
119: /**
120: * Is the current page the first one?
121: * @return bool
122: */
123: public function isFirst()
124: {
125: return $this->getPageIndex() === 0;
126: }
127:
128:
129: /**
130: * Is the current page the last one?
131: * @return bool
132: */
133: public function isLast()
134: {
135: return $this->itemCount === NULL ? FALSE : $this->getPageIndex() >= $this->getPageCount() - 1;
136: }
137:
138:
139: /**
140: * Returns the total number of pages.
141: * @return int|NULL
142: */
143: public function getPageCount()
144: {
145: return $this->itemCount === NULL ? NULL : (int) ceil($this->itemCount / $this->itemsPerPage);
146: }
147:
148:
149: /**
150: * Sets the number of items to display on a single page.
151: * @param int
152: * @return static
153: */
154: public function setItemsPerPage($itemsPerPage)
155: {
156: $this->itemsPerPage = max(1, (int) $itemsPerPage);
157: return $this;
158: }
159:
160:
161: /**
162: * Returns the number of items to display on a single page.
163: * @return int
164: */
165: public function getItemsPerPage()
166: {
167: return $this->itemsPerPage;
168: }
169:
170:
171: /**
172: * Sets the total number of items.
173: * @param int (or NULL as infinity)
174: * @return static
175: */
176: public function setItemCount($itemCount)
177: {
178: $this->itemCount = ($itemCount === FALSE || $itemCount === NULL) ? NULL : max(0, (int) $itemCount);
179: return $this;
180: }
181:
182:
183: /**
184: * Returns the total number of items.
185: * @return int|NULL
186: */
187: public function getItemCount()
188: {
189: return $this->itemCount;
190: }
191:
192:
193: /**
194: * Returns the absolute index of the first item on current page.
195: * @return int
196: */
197: public function getOffset()
198: {
199: return $this->getPageIndex() * $this->itemsPerPage;
200: }
201:
202:
203: /**
204: * Returns the absolute index of the first item on current page in countdown paging.
205: * @return int|NULL
206: */
207: public function getCountdownOffset()
208: {
209: return $this->itemCount === NULL
210: ? NULL
211: : max(0, $this->itemCount - ($this->getPageIndex() + 1) * $this->itemsPerPage);
212: }
213:
214:
215: /**
216: * Returns the number of items on current page.
217: * @return int|NULL
218: */
219: public function getLength()
220: {
221: return $this->itemCount === NULL
222: ? $this->itemsPerPage
223: : min($this->itemsPerPage, $this->itemCount - $this->getPageIndex() * $this->itemsPerPage);
224: }
225:
226: }
227: