source: trunk/lib/PageNumbers.inc.php @ 768

Last change on this file since 768 was 768, checked in by anonymous, 2 years ago

Minor improvements

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