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