Making BSPagination an abstract class that people extend instead of using callback...
[isso.git] / Pagination.php
1 <?php
2 /*=====================================================================*\
3 || ###################################################################
4 || # Blue Static ISSO Framework
5 || # Copyright (c)2005-2008 Blue Static
6 || #
7 || # This program is free software; you can redistribute it and/or modify
8 || # it under the terms of the GNU General Public License as published by
9 || # the Free Software Foundation; version 2 of the License.
10 || #
11 || # This program is distributed in the hope that it will be useful, but
12 || # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 || # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 || # more details.
15 || #
16 || # You should have received a copy of the GNU General Public License along
17 || # with this program; if not, write to the Free Software Foundation, Inc.,
18 || # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 || ###################################################################
20 \*=====================================================================*/
21
22 /**
23 * Pagination System (Pagination.php)
24 *
25 * @package ISSO
26 */
27
28 /**
29 * Pagination System
30 *
31 * On many pages, it is necessary to limit the amount of records to display.
32 * Using this class, you can set the maximum and minimum values to display,
33 * and then the input variables for page number and perpage. This will
34 * then create a page navigator and manage the SQL LIMIT statements.
35 *
36 * @author Blue Static
37 * @copyright Copyright (c)2005 - 2008, Blue Static
38 * @package ISSO
39 *
40 */
41 abstract class BSPagination
42 {
43 /**
44 * Current page number
45 * @var integer
46 */
47 protected $page;
48
49 /**
50 * Per-page value
51 * @var integer
52 */
53 protected $perpage;
54
55 /**
56 * Number of page links
57 * @var integer
58 */
59 protected $pagelinks;
60
61 /**
62 * Total number of results
63 * @var integer
64 */
65 protected $total;
66
67 /**
68 * Total number of pages
69 * @var integer
70 */
71 protected $pagecount;
72
73 /**
74 * Maximum number of per-page results
75 * @var integer
76 */
77 protected $maxperpage = 100;
78
79 /**
80 * Default number of per-page results
81 * @var integer
82 */
83 protected $defaultperpage = 20;
84
85 // ###################################################################
86 /**
87 * Callback public function for the processing of an indivdual page link
88 *
89 * @param string The base link
90 * @param boolean Wether or not the item is the current page
91 * @param integer Page number
92 *
93 * @return string Compiled HTML
94 */
95 protected abstract function _bitProcessor($baselink, $isCurrent, $pagenumber);
96
97 // ###################################################################
98 /**
99 * Callback public function for the processing the entire page navigator
100 *
101 * @param string The base link
102 * @param integer Next page number
103 * @param integer Previous page number
104 * @param array Show options: array('first' => (boolean)first page link, 'last' => boolean, 'prev' => boolean, 'next' => boolean)
105 * @param string Bits to process
106 *
107 * @return string Compiled HTML
108 */
109 protected abstract function _navigationProcessor($baselink, $next, $prev, $show, $bits);
110
111 /**
112 * Set the Pagination->perpage and Pagination->page variables
113 */
114 protected abstract function _setVariables();
115
116 /**
117 * Constructor
118 */
119 public function __construct()
120 {
121 if (!BSApp::$input instanceof BSInput)
122 {
123 throw new Exception('BSApp::$input is not an instance of BSInput');
124 }
125 }
126
127 // ###################################################################
128 /**
129 * Returns the current page number
130 *
131 * @return integer Current page
132 */
133 public function getPage()
134 {
135 return $this->page;
136 }
137
138 // ###################################################################
139 /**
140 * Returns the current perpage value
141 *
142 * @return integer Current perpage
143 */
144 public function getPerPage()
145 {
146 return $this->perpage;
147 }
148
149 // ###################################################################
150 /**
151 * Sets total
152 *
153 * @param integer Total number
154 */
155 public function setTotal($total)
156 {
157 $this->total = $total;
158 }
159
160 // ###################################################################
161 /**
162 * Returns the number of pages to be in the navigator
163 *
164 * @param integer Number of pages
165 */
166 public function getPageCount()
167 {
168 return $this->pagecount;
169 }
170
171 // ###################################################################
172 /**
173 * Takes all of the information from the set() functions and then
174 * prepares all of the data through verification
175 */
176 public function processIncomingData()
177 {
178 $this->_setVariables();
179 $this->page = BSApp::$input->clean($this->page, TYPE_INT);
180 $this->perpage = BSApp::$input->clean($this->perpage, TYPE_INT);
181 $this->pagelinks = BSApp::$input->clean($this->pagelinks, TYPE_INT);
182
183 if ($this->page <= 0)
184 {
185 $this->page = 1;
186 }
187
188 if ($this->perpage <= 0)
189 {
190 $this->perpage = $this->defaultperpage;
191 }
192 if ($this->perpage > $this->maxperpage)
193 {
194 $this->perpage = $this->maxperpage;
195 }
196
197 $this->perpage = BSApp::$input->clean($this->perpage, TYPE_INT);
198 }
199
200 // ###################################################################
201 /**
202 * Takes the variables and splits up the pages
203 */
204 public function splitPages()
205 {
206 $this->pagecount = ceil($this->total / $this->perpage);
207 if ($this->pagelinks == 0)
208 {
209 $this->pagelinks = $this->pagecount;
210 }
211 }
212
213 // ###################################################################
214 /**
215 * Returns the lower limit of the pages
216 *
217 * @param integer Page number
218 *
219 * @return integer Lower result limit
220 */
221 public function fetchLimit($page = null)
222 {
223 if ($page === null)
224 {
225 $page = $this->page;
226 }
227
228 $limit = $page * $this->perpage;
229
230 if ($page < 1)
231 {
232 $page = 1;
233 $limit = 0;
234 }
235 else if ($page > $this->pagecount)
236 {
237 $page = $this->pagecount - 1;
238 $limit = $this->total;
239 }
240
241 if ($limit < 0)
242 {
243 return 0;
244 }
245 else if ($limit > $this->total)
246 {
247 return $this->total;
248 }
249 else
250 {
251 return $limit;
252 }
253 }
254
255 // ###################################################################
256 /**
257 * Constructs the page navigator
258 *
259 * @param string Base link path
260 * @param bool Add a ? or a & to the path so it's link-friendly
261 *
262 * @return string Generated HTML page navigator
263 */
264 public function constructPageNav($baselink, $addParam = true)
265 {
266 // handle base link
267 if ($addParam)
268 {
269 if (strpos($baselink, '?') === false)
270 {
271 $baselink .= '?';
272 }
273 else if (!strpos($baselink, '#\?$#') && !strpos($baselink, '&'))
274 {
275 $baselink .= '&amp;';
276 }
277 }
278
279 // first page number in page nav
280 $startpage = $this->page - $this->pagelinks;
281 if ($startpage < 1)
282 {
283 $startpage = 1;
284 }
285
286 // last page number in page nav
287 $endpage = $this->page + $this->pagelinks;
288 if ($endpage > $this->pagecount)
289 {
290 $endpage = $this->pagecount;
291 }
292
293 // prev page in page nav
294 $prevpage = $this->page - 1;
295 if ($prevpage < 1)
296 {
297 $prevpage = 1;
298 }
299
300 // next page in page nav
301 $nextpage = $this->page + 1;
302 if ($nextpage > $this->pagecount)
303 {
304 $nextpage = $this->pagecount;
305 }
306
307 // show the prev page
308 $show['prev'] = true;
309 if ($this->page == $startpage)
310 {
311 $show['prev'] = false;
312 }
313
314 // show the next page
315 $show['next'] = true;
316 if ($this->page == $endpage)
317 {
318 $show['next'] = false;
319 }
320
321 // show the first page
322 $show['first'] = false;
323 if ($startpage > 1)
324 {
325 $show['first'] = true;
326 }
327
328 // show the last page
329 $show['last'] = false;
330 if ($endpage < $this->pagecount)
331 {
332 $show['last'] = true;
333 }
334
335 // construct the page bits
336 $bits = '';
337 for ($i = $startpage; $i <= $endpage; $i++)
338 {
339 if ($i == $this->page)
340 {
341 $nolink = true;
342 }
343 else
344 {
345 $nolink = false;
346 }
347
348 $bits .= $this->_bitProcessor($baselink, $nolink, $i);
349 }
350
351 return $this->_navigationProcessor($baselink, $nextpage, $prevpage, $show, $bits);
352 }
353 }
354
355 ?>