source: trunk/lib/PageNumbers.inc.php

Last change on this file was 812, checked in by anonymous, 7 weeks ago

Fix depreciation notices

File size: 14.3 KB
Line 
1<?php
2/**
3 * The Strangecode Codebase - a general application development framework for PHP
4 * For details visit the project site: <http://trac.strangecode.com/codebase/>
5 * Copyright 2001-2012 Strangecode, LLC
6 *
7 * This file is part of The Strangecode Codebase.
8 *
9 * The Strangecode Codebase is free software: you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published by the
11 * Free Software Foundation, either version 3 of the License, or (at your option)
12 * any later version.
13 *
14 * The Strangecode Codebase is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/**
24 * PageNumbers.inc.php
25 *
26 * The PageNumbers class provides a common abstracted interface to the
27 * multiple pages features. It sets the various numbers needed to display items
28 * on a page, and includes functions for working with these numbers.
29 * You must call set setTotalItems(), setPerPage() and setPageNumber() before calling calculate()
30 * this the other various values will be set automatically. Then you can call printPerPageLinks,
31 * printPageNumbers, etc, and use the various page object properties in your page templates.
32 *
33 * @author    Quinn Comendant <quinn@strangecode.com>
34 * @version   1.61
35 */
36
37require_once dirname(__FILE__) . '/Prefs.inc.php';
38
39class PageNumbers
40{
41
42    public $total_items;       // Total quantity of items.
43    public $total_pages;       // The total number of pages.
44    public $current_page = 1;  // Current page number.
45    public $first_item;        // The counter for the first item on this page (zero index).
46    public $last_item;         // The counter for the last item on this page (zero index).
47    public $max_num_links = 5; // The max number of links to show on page (odd numbers look best).
48    protected $_num_links;        // The number of links to show on page.
49    protected $_per_page = 50;    // Items per page.
50
51    // Flags to ensure all necessary values have been set before calling calculate().
52    public $set_per_page_initialized = false;
53    public $set_page_number_initialized = false;
54    public $set_total_items_initialized = false;
55
56    // These are initialized in the constructor.
57    public $per_page_options;
58    public $left_arrow;
59    public $left_arrow_disabled;
60    public $left_dbl_arrow;
61    public $left_dbl_arrow_disabled;
62    public $right_arrow;
63    public $right_arrow_disabled;
64    public $right_dbl_arrow;
65    public $right_dbl_arrow_disabled;
66    public $url_base;
67    public $prefs;
68
69    /**
70     * PageNumbers constructor. All arguments are depreciated. Use set* functions instead.
71     */
72    public function __construct()
73    {
74        // Default options for the quantity per page links.
75        $this->per_page_options = array(50, 100, 250, 1000);
76
77        // Default options for the page number links.
78        $this->left_arrow = _("back");
79        $this->left_arrow_disabled = '<span style="color: #aaaaaa;">' . _("back") . '</span>';
80        $this->left_dbl_arrow = '<strong>&laquo;</strong>';
81        $this->left_dbl_arrow_disabled = '<span style="color: #aaaaaa;"><strong>&laquo;</strong></span>';
82        $this->right_arrow = _("next");
83        $this->right_arrow_disabled = '<span style="color: #aaaaaa;">' . _("next") . '</span>';
84        $this->right_dbl_arrow = '<strong>&raquo;</strong>';
85        $this->right_dbl_arrow_disabled = '<span style="color: #aaaaaa;"><strong>&raquo;</strong></span>';
86
87        // Default url base. This will be set manually after instantiation
88        // in special cases like using a /my/page/# scheme.
89        $this->url_base = $_SERVER['PHP_SELF'] . '?page_number=';
90
91        $this->prefs = new Prefs($_SERVER['PHP_SELF']);
92        $this->prefs->setParam(array('persistent' => false));
93    }
94
95    private function _validNumber($num)
96    {
97        if (!isset($num) || '' == $num) {
98            return false;
99        }
100        return preg_match('/^\d+$/', $num);
101    }
102
103    /**
104     * Set the number of items per page.
105     */
106    public function setPerPage($per_page, $default=25, $save_value=true)
107    {
108        // (1) By provided argument, if valid.
109        // (2) By saved preference, if available.
110        // (3) Set to default value if provided and valid.
111        // (4) Keep as Class default of 25.
112        if ($this->_validNumber($per_page) && $per_page > 0) {
113            $this->_per_page = $per_page;
114            if ($save_value) {
115                $this->prefs->set('items_per_page', $this->_per_page);
116            }
117        } else if ($save_value && $this->prefs->exists('items_per_page')) {
118            $this->_per_page = (int)$this->prefs->get('items_per_page');
119        } else if ($this->_validNumber($default) && $default > 0) {
120            $this->_per_page = $default;
121        }
122        $this->set_per_page_initialized = true;
123    }
124
125    /**
126     * Set the current page number.
127     */
128    public function setPageNumber($page_number, $save_value=true)
129    {
130        // (1) By provided argument, if valid.
131        // (2) By saved preference, if available.
132        // (3) Don't change from what was provided at class instantiation.
133        if ($this->_validNumber($page_number)) {
134            if ($page_number < 1) {
135                // FIXME: How to go back around to the last page? Hmmm. Set to 1 for now.
136                $this->current_page = 1;
137            } else {
138                $this->current_page = $page_number;
139            }
140            if ($save_value) {
141                $this->prefs->set('page_number', $this->current_page);
142            }
143        } else if ($save_value && $this->prefs->exists('page_number')) {
144            $this->current_page = (int)$this->prefs->get('page_number');
145        }
146        $this->set_page_number_initialized = true;
147    }
148
149    /**
150     * Set the total number of items.
151     */
152    public function setTotalItems($total_items)
153    {
154        if ($this->_validNumber($total_items) && $total_items > 0) {
155            $this->total_items = $total_items;
156        } else {
157            $this->total_items = 0;
158        }
159        $this->set_total_items_initialized = true;
160    }
161
162    /**
163     * After $total_items or other options are set, this function calculates
164     * all the other numbers needed. If you set any variables manually,
165     * for example if $page_number comes from
166     * some place other than the GET or POST array, you should call this
167     * function manually, otherwise it happens at object instantiation.
168     *
169     * @access public
170     */
171    public function calculate()
172    {
173        $app =& App::getInstance();
174
175        if (!$this->set_per_page_initialized) {
176            $app->logMsg(sprintf('set_per_page not initialized'), LOG_ERR, __FILE__, __LINE__);
177        }
178        if (!$this->set_page_number_initialized) {
179            $app->logMsg(sprintf('set_page_number not initialized'), LOG_ERR, __FILE__, __LINE__);
180        }
181        if (!$this->set_total_items_initialized) {
182            $app->logMsg(sprintf('set_total_items not initialized'), LOG_ERR, __FILE__, __LINE__);
183        }
184
185        // If the specified page exceeds total pages or is less than 1, set the page to 1.
186        if ($this->_per_page * $this->current_page >= $this->total_items + $this->_per_page || $this->_per_page * $this->current_page < 1) {
187            $this->current_page = 1;
188        }
189
190        // The first item to be shown on this page.
191        $this->first_item = ($this->current_page - 1) * $this->_per_page;
192
193        // The last item to be shown on this page.
194        if ($this->total_items < $this->current_page * $this->_per_page) {
195            $this->last_item = $this->total_items - 1;
196        } else {
197            $this->last_item = $this->current_page * $this->_per_page - 1;
198        }
199
200        // Zeroing. Just in case. Paranoia. Yeah, negative numbers perturb me.
201        if ($this->first_item < 1) {
202            $this->first_item = 0;
203        }
204        if ($this->last_item < 1) {
205            $this->last_item = 0;
206        }
207        if ($this->total_items < 1) {
208            $this->total_items = 0;
209        }
210
211        // The total number of pages.
212        $this->total_pages = ceil($this->total_items / $this->_per_page);
213
214        // Figure out how many page number links to print.
215        if ($this->total_pages >= $this->max_num_links) {
216            $this->_num_links = $this->max_num_links;
217        } else {
218            $this->_num_links = $this->total_pages;
219        }
220    }
221
222    /**
223     * Returns the SQL code to limit query to items that are on current page.
224     */
225    public function getLimitSQL()
226    {
227        $app =& App::getInstance();
228        $db =& DB::getInstance();
229
230        if ($this->_validNumber($this->first_item) && $this->_validNumber($this->_per_page)) {
231            return ' LIMIT ' . $db->escapeString($this->first_item) . ', ' . $db->escapeString($this->_per_page) . ' ';
232        } else {
233            $app->logMsg(sprintf('Could not find SQL to LIMIT by %s %s.', $this->first_item, $this->_per_page), LOG_WARNING, __FILE__, __LINE__);
234            return '';
235        }
236    }
237
238    /**
239     * Prints links to change the number of items shown per page.
240     *
241     * @access public
242     */
243    public function printPerPageLinks($query_key='per_page')
244    {
245        $app =& App::getInstance();
246
247        $sp = '';
248        for ($i=0; $i<sizeof($this->per_page_options); $i++) {
249            if ($this->_per_page != $this->per_page_options[$i]) {
250                printf('%s<a href="%s">%s</a>',
251                    $sp,
252                    $app->oHREF($_SERVER['PHP_SELF'] . '?' . $query_key . '=' . $this->per_page_options[$i]),
253                    $this->per_page_options[$i]
254                );
255            } else {
256                echo $sp . '<strong>' . $this->per_page_options[$i] . '</strong>';
257            }
258            $sp = '&nbsp;';
259        }
260    }
261
262    /**
263     * Outputs an $app->oHREF compatible url that goes to the page $page_number.
264     * Depends on $this->base_url to build the url onto. This is used in the
265     * page_number.ihtml template.
266     *
267     * @param  int   $page_number    The page number this page will go to.
268     *
269     * @return string                The URL.
270     *
271     * @access public
272     */
273    public function getPageNumURL($page_number, $carry_args=null)
274    {
275        $app =& App::getInstance();
276
277        return $app->oHREF($this->url_base . $page_number, $carry_args);
278    }
279    public function printPageNumURL($page_number, $carry_args=null)
280    {
281        echo $this->getPageNumURL($page_number, $carry_args);
282    }
283
284    /**
285     * Returns an array of page number links.
286     *
287     * @access public
288     */
289    public function getPageNumbersArray($carry_args=null)
290    {
291        $page_numbers = array();
292
293        for ($i = 1; $i <= $this->total_pages; $i++) {
294            $page_numbers[] = array(
295                'number' => $i,
296                'url' => $this->getPageNumURL($i, $carry_args),
297                'current' => ($this->current_page == $i)
298            );
299        }
300
301        return $page_numbers;
302    }
303
304    /**
305     * Returns a string containing the page number links.
306     *
307     * @access public
308     */
309    public function getPageNumbers($carry_args=null)
310    {
311        $page_numbers_string = '';
312
313        if ($this->current_page > $this->total_pages - floor($this->_num_links / 2)) {
314            $high_num = $this->total_pages;
315            $low_num = $high_num - $this->_num_links + 1;
316        } else {
317            $low_num = $this->current_page - floor($this->_num_links / 2);
318            if ($low_num < 1) {
319                $low_num = 1;
320            }
321            $high_num = $low_num + $this->_num_links - 1;
322        }
323
324        if ($this->current_page != 1) {
325            // Print "first" and "previous" page links.
326            if ($this->left_dbl_arrow) {
327                $page_numbers_string .= sprintf('<a href="%s" title="%s">%s</a>&nbsp;', $this->getPageNumURL(1, $carry_args), _("Go to the first page"), $this->left_dbl_arrow);
328            }
329            if ($this->left_arrow) {
330                $page_numbers_string .= sprintf('<a href="%s" title="%s">%s</a>&nbsp;&nbsp;', $this->getPageNumURL($this->current_page - 1, $carry_args), _("Go back one page"), $this->left_arrow);
331            }
332            // Print links to specific page numbers before the current page.
333            for ($i = $low_num; $i < $this->current_page; $i++) {
334                $page_numbers_string .= sprintf('<a href="%s">%s</a>&nbsp;', $this->getPageNumURL($i, $carry_args), $i);
335            }
336        } else {
337            if ($this->left_dbl_arrow) {
338                $page_numbers_string .= $this->left_dbl_arrow_disabled . '&nbsp;';
339            }
340            if ($this->left_arrow) {
341                $page_numbers_string .= $this->left_arrow_disabled . '&nbsp;';
342            }
343        }
344
345        if ($this->_num_links > 0) {
346            // Print the current page number.
347            $page_numbers_string .= sprintf('<strong>%s</strong>&nbsp;', $this->current_page);
348        }
349
350        if ($this->current_page < $this->total_pages) {
351            // Print links to specific page numbers after the current page.
352            for ($i = $this->current_page + 1; $i <= $high_num; $i++) {
353                $page_numbers_string .= sprintf('<a href="%s">%s</a>&nbsp;', $this->getPageNumURL($i, $carry_args), $i);
354            }
355            // Print "last" and "next" page links.
356            if ($this->right_arrow) {
357                $page_numbers_string .= sprintf('<a href="%s" title="%s">%s</a>&nbsp;&nbsp;', $this->getPageNumURL($this->current_page + 1, $carry_args), _("Go forward one page"), $this->right_arrow);
358            }
359            if ($this->right_dbl_arrow) {
360                $page_numbers_string .= sprintf('<a href="%s" title="%s">%s</a>&nbsp;&nbsp;', $this->getPageNumURL($this->total_pages, $carry_args), _("Go to the last page"), $this->right_dbl_arrow);
361            }
362        } else {
363            if ($this->right_arrow_disabled) {
364                $page_numbers_string .= $this->right_arrow_disabled . '&nbsp;';
365            }
366            if ($this->right_dbl_arrow_disabled) {
367                $page_numbers_string .= $this->right_dbl_arrow_disabled;
368            }
369        }
370
371        return $page_numbers_string;
372    }
373
374    public function printPageNumbers($carry_args=null)
375    {
376        echo $this->getPageNumbers($carry_args);
377    }
378
379}
380
Note: See TracBrowser for help on using the repository browser.