Pager class
| From: | and | Date: | Tue, 05 Mar 2002 09:31:27 +0000 |
| Subject: | Pager class | ||
| Groups: | php.pear.dev | ||
| Request: | Send a blank email to pear-dev+get-4899@lists.php.net to get a copy of this message | ||
According to PEAR commiting rules I represent Pager class.
I use it very often in my work and may be it will be useful for somebody else.
Pager draws nothing itself but only calculates values necessary for drawing
lists splitted into number of pages.
It takes number of page and returns such values:
1. Subset of list items which must be placed on current page
Pager supports 2 modes:
1. Full list mode
In this mode all items in list assigned to Pager as array and result of it
work is array of items which must be placed on this page.
This mode can be useful when you use very complex query to database or you
get items some other way then data basequery and can't specify offset and
limit.
2. Limit-Offset mode
In this mode class user specify only the number of items in list and then
get offset of first item on page and number (limit) of items on this page.
This mode can be useful when number of items in list very large and it is too
expensive to underway them as single array.
2 . Data which required to draw list navigation bar
- array of nearest page numbers which must be shown in bar
- number of current page
- number of previous and next pages which not shown in bar
- number of last page
for example if current page is 8 and we want to show 5 nearest pages in bar
and have 17 pages at all we can draw having such data:
[<<] [<] 6 7 [8] 9 10 [>][>>]
where
6 7 9 10 - links to corresponding pages
[8] - current page (inactive)
[<] - link to page 5
[>] - link to page 11
[<<] - link to page 1
[>>] - link to page 17 (last page)
if we select [<] we will get:
1 2 3 4 [5] [>][>>]
where
[5] - current page
[>] - link to page 6
[>>] - link to page 17
and so on ...
Methods of Pager class:
Class Pager has constructor with 3 arguments:
Pager($mode = PAGER_FULL_LIST_MODE, $itemsOnPage = 20, $pagesInBar = 10);
where
$mode - mode of Pager
PAGER_FULL_LIST_MODE or PAGER_LIMIT_OFFSET_MODE
$itemsOnPage - number of items on page
$pagesInBar - number of pages in bar
setItems(&$items) - set items of list
where $items -
in Full list mode is array of items in list
in Limit-Offset mode is number of items in list
&setCurrentPage($pageNumber = 1)
where $pageNumber - number of page
this function returns object of class which contain all necessary data
Methods of PagerState class:
getOuterLeftPage()
- returns number of page previous to first in bar or 0 if such page does not
exists
getOuterRightPage()
- returns number of page next to last in bar or 0 if such page does not
exists
getLastPage()
- returns number of last page
&getBar()
- returns array of page numbers which must be drawn in bar
getBarCurrentPage()
- returns number of selected page in bar
countPagesInBar()
- returns number of pages in bar
&getItems()
in Full list mode returns array of items which must be placed on selected page
in Limit-Offset mode returns associative array with 2 members:
'offset' => offset of first item on page
'limit' => number of items on page
Pager class after calling setItems() method can be stored in session,
or serialized in other way and then only setCurrentPage() method can be called
when page is changed.
If maintainers of PEAR project will be interested in this class I will
prepare full documentation on it and comment sources more verbose.
Andrey Djachenko
This is source code for PagerState and Pager classes:
<?php
define('PAGER_FULL_LIST_MODE', 0);
define('PAGER_LIMIT_OFFSET_MODE', 1);
class PagerState
{
var $_leftOuterPage = 0;
var $_rigthOuterPage = 0;
var $_lastPage = 0;
var $_bar; //array
var $_barCurrentPage = 0;
var $_items; //array
function getOuterLeftPage() {return $this->_leftOuterPage;}
function getOuterRightPage() {return $this->_rigthOuterPage;}
function getLastPage() {return $this->_lastPage;}
function &getBar() {return $this->_bar;}
function getBarCurrentPage() {return $this->_barCurrentPage;}
function countPagesInBar() {return sizeof($this->_bar);}
function &getItems() {return $this->_items;}
}
class Pager
{
var $_itemsOnPage = 0;
var $_pagesInBar = 1;
var $_items; //array
var $_itemsNumber = 0;
var $_decades = 0;
var $_pagesInLastDecade = 0;
var $_pages = 0;
var $_itemsOnLastPage = 0;
var $_mode = PAGER_FULL_LIST_MODE;
////////////////////////////////////////////////////////////////////////
function Pager($mode = PAGER_FULL_LIST_MODE,
$itemsOnPage = 20, $pagesInBar = 10)
{
$this->_mode = $mode;
$this->_itemsOnPage = $itemsOnPage;
$this->_pagesInBar = $pagesInBar;
}
////////////////////////////////////////////////////////////////////////
function setItems(&$items)
{
if ($this->_mode == PAGER_FULL_LIST_MODE) {
$this->_items = (is_array($items)) ? $items : array();
$this->_itemsNumber = sizeof($this->_items);
$this->_init();
} else if ($this->_mode == PAGER_LIMIT_OFFSET_MODE) {
$this->_itemsNumber = (is_numeric($items)
&& (int)$items > 0) ? $items : 0;
$this->_init();
}
}
////////////////////////////////////////////////////////////////////////
function &setCurrentPage($pageNumber = 1)
{
if ($pageNumber < 1) {
$pageNumber = 1;
}
if ($pageNumber > $this->_pages - 1) {
$pageNumber = $this->_pages;
}
$current_decade = ($pageNumber - 1) / $this->_pagesInBar;
$current_decade = (int)$current_decade + 1;
$ps = new PagerState;
//items
$first = ($pageNumber != 1) ?
($pageNumber - 1) * $this->_itemsOnPage : 0;
$number = ($pageNumber != $this->_pages) ?
$this->_itemsOnPage : $this->_itemsOnLastPage;
if ($this->_mode == PAGER_FULL_LIST_MODE) {
$ps->_items = ($this->_itemsNumber > 0) ?
array_slice($this->_items, $first, $number) : array();
} else if ($this->_mode == PAGER_LIMIT_OFFSET_MODE) {
$ps->_items = ($this->_itemsNumber > 0) ?
array('offset'=>$first, 'limit'=>$number) :
array('offset'=>0, 'limit'=>0);
}
//pages in bar
if ($this->_pages == 0) {
$number = 0;
} else if ($current_decade == $this->_decades) {
$number = $this->_pages % $this->_pagesInBar;
if ($number == 0) {
$number = $this->_pagesInBar;
}
} else {
$number = $this->_pagesInBar;
}
$first = $current_decade - 1;
$first = (int)$first;
$first = $first * $this->_pagesInBar + 1;
$index = $pageNumber % $this->_pagesInBar;
$index = ($index == 0) ? $this->_pagesInBar - 1 : $index - 1;
for ($i = 0; $i < $number; $i++) {
$s[] = $first + $i;
}
$ps->_bar = $s;
$ps->_barCurrentPage = $ps->_bar[$index];
//left link
$ps->_leftOuterPage = ($current_decade > 1) ? $first - 1 : 0;
//rigth link
$ps->_rigthOuterPage = ($current_decade < $this->_decades) ?
$first + $number : 0;
//last page
$ps->_lastPage = $this->_pages;
return $ps;
}
////////////////////////////////////////////////////////////////////////
function _init()
{
$this->_pages = $this->_itemsNumber / $this->_itemsOnPage;
$this->_pages = (int)$this->_pages;
$this->_itemsOnLastPage = $this->_itemsNumber % $this->_itemsOnPage;
if ($this->_itemsOnLastPage > 0) {
$this->_pages++;
} else {
$this->_itemsOnLastPage = $this->_itemsOnPage;
}
$this->_decades = $this->_pages / $this->_pagesInBar;
$this->_decades = (int)$this->_decades;
$this->_pagesInLastDecade = $this->_pages % $this->_pagesInBar;
if ($this->_pagesInLastDecade > 0) {
$this->_decades++;
} else {
$this->_pagesInLastDecade = $this->_pagesInBar;
}
}
////////////////////////////////////////////////////////////////////////
}
?>