<?php
/**
tablepager - php pager for splitting up database rows/items on to multiple pages
Version 0.1.1
Copyright (C) 2003 Greg MacLellan
Aug 22/2003

greg at mtechsolutions dot ca

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    http://www.gnu.org/licenses/lgpl.html


There's still a couple things this doesnt do (inconsistent with the examples, btw!)

If surrounding = 2, and the currentpage is 4, it will show:
"... 2 3 4 5 6 ..."

There's really no point in blocking "1" with "...", so that should override that behaviour

Same thing happens when firstlast = true, if surrounding = 2 and currentpage = 5,
"1 ... 3 4 5 6 7 ... 12"

There's no point in blocking the "2". I started to add an override for this (in the 
"if ($cond_notblocked == false)" section on line 131), but never finished it. If anyone cares,
feel free.


I also don't know if appending to a string is really the best way to build the output,
it might be more efficient with an array and then using implode() later? Just a thought,
this was just hacked together fairly quickly, but I hope it will be useful to others, 
which is why I released it under LGPL.

If you make any fixes, or have comments, email me. Address is above

-greg

*/
class tablepager {
    var 
$_totalRows;
    var 
$_rowsPerPage;
    var 
$_currentPage;

    
/** Create a new tablepager, for splitting up rows from a database or other list into
     * seperate pages
     * @param int    $totalRows    Total number of rows in the full result set
     * @param int    $rowsPerPage    How many rows to display per page
     * @param int    $currentPage    The current page number (starting at 1)
     */
    
function tablepager($totalRows$rowsPerPage$currentPage 1) {
        
$this->_totalRows $totalRows;
        
$this->_rowsPerPage $rowsPerPage;
        
$this->_currentPage $currentPage;
    }

    
/** The number of pages
     */
    
function getNumPages() {
        return 
ceil($this->_totalRows $this->_rowsPerPage);
    }

    
/** The current offset into the results
     */
    
function getOffset() {
        return 
$this->_currentPage $this->_rowsPerPage;
    }

    
/** Returns a limit clause for SQL statments, based on current page
    */
    
function getLimitClause() {
        return 
"LIMIT ".$this->_rowsPerPage.",".$this->getOffset();
    }
    
    
/** Show a page selector
     * Example matrix: (12 pages total, 8 is current page
     *  Output                            $surrounding $nextprev $firstlast
     *  --------------------------------- ------------ --------- ----------
     *  < 1 .. 7 8 9 .. 12 >              1            true      true
     *  < .. 7 8 9 .. >                   1            true      false
     *  1 .. 7 8 9 .. 12                  1            false     true
     *  < 1 .. 5 6 7 8 9 10 11 12 >       3            true      true
     *  < 1 .. 6 7 8 9 10 11 12 >         2            true      true
     *  < 1 2 3 4 5 6 7 8 9 10 11 12 >    false        true      true
     *
     *
     * @param string    $urlprefix    Should be of the form "file.php?page=". The page
     *                    number will be concatenated on to the end
     * @param int        $surrounding    Controls blanking out of page numbers. If False,
     *                    all page numbers are shown. If any integer, then
     *                    that number of page numbers are shown next to
     *                    the current page, and the rest are seperated with "..."
     * @param bool        $nextprev    True to show < and > arrows at the ends of the string,
     *                    to link to previous/next page
     * @param bool        $firstlast    True to always show a number for the first and last
     *                    pages, regardless of $surrounding setting. This has
     *                    no effect if $surrounding = false, since all pages
     *                    are shown anyways.
    */
    
function showPager($urlprefix$surrounding false$nextprev true$firstlast true) {
        
$out "";
        if (
$nextprev && ($this->_currentPage 1)) {
            
// show previous button, if applicable
            
$out .= "<a href=\"".$urlprefix.($this->_currentPage 1)."\">&lt;</a>&nbsp;";
        }

        
$total $this->getNumPages();

        for (
$i 1$i <= $total$i++) {
            
$cond_showall false;
            
$cond_notblocked false;
            
$cond_firstlast false;
            
//echo " [$i]";

            // not blocking any numbers, so show them all
            
$cond_showall = ($surrounding === false);
            
//echo ($cond_showall ? "<b>1</b>" : "1");

            
if (!$cond_showall) {
                
// if we are blocking, is this within +/- $surrounding numbers from current page?
                
$cond_notblocked = (abs($this->_currentPage $i) <= $surrounding);
                
//echo ($cond_notblocked ? "<b>2</b>" : "2");

                
if ($cond_notblocked == false) {
                    
// its blocked, lets check if it should be unblocked
                    
if ($firstlast) {
                        
//$cond_notblocked = ($i <= 2);
                    
} else {
                    }
                }

                
// if using $firstlast, then if this is the first or last, show it
                
$cond_firstlast = ($firstlast && (($i == 1) || ($i == $total)));
                
//echo ($cond_firstlast ? "<b>3</b>" : "3");
            
}

            if (
$cond_showall || $cond_notblocked || $cond_firstlast) {
                if (
$this->_currentPage == $i) {
                    
$out .= $i."&nbsp";
                } else {
                    
$out .= "<a href=\"".$urlprefix.$i."\">".$i."</a>&nbsp;";
                }
            } else {
                
$out .= ".";
            }
        }

        if (
$nextprev && ($this->_currentPage $total)) {
            
// show next button, if applicable
            
$out .= "<a href=\"".$urlprefix.($this->_currentPage 1)."\">&gt;</a>&nbsp;";
        }
        
        
// replace all our non-numbers with just "..."
        // probably not the most efficient way, but works well
        
$out preg_replace("/\.+/","... ",$out);

        return 
$out;
    }
}

echo 
"<p>showPager(surrounding = 2, nextprev = true, firstlast = true)<br>";
for (
$i 1$i 13$i++) {
    
$pager = new tablepager(11510$i);
    echo 
$pager->showPager("?page="2truetrue)."<br>";
}

echo 
"<p>showPager(surrounding = 2, nextprev = true, firstlast = false)<br>";
for (
$i 1$i 13$i++) {
    
$pager = new tablepager(11510$i);
    echo 
$pager->showPager("?page="2truefalse)."<br>";
}

echo 
"<p>showPager(surrounding = false, nextprev = true, firstlast = true)<br>";
for (
$i 1$i 13$i++) {
    
$pager = new tablepager(11510$i);
    echo 
$pager->showPager("?page="falsetruetrue)."<br>";
}

?>