Ok, here is a more complete set of classes. I proceeded with the design that the Pager would only generate page numbers -- supporting first, prev, next, last, and ranges of page numbers. The PagerHTMLWriter class then supports creating URLs and full links. This code has gotten a lot more complex quickly and I am not sure that the design is still right. It needs a bunch of decisions about what to do on errors and edge conditions, and whether all these getters should be included. A refactor is in order.
Here is the Pager.php file that has the base Pager class and the PagerHTMLWriter class that outputs links:
Code: Select all
class Pager {
var $datasource = null; // PagerArrayDatasource object
var $page_size = 10; // number of rows of data per page
var $range_size = 10; // number of links in pager
var $current_page = 0;
var $first_page = 1;
var $last_page = -1;
var $first_row = 1;
var $last_row = 0;
var $start_row = 0;
var $end_row = 0;
var $page_url = '';
var $page_param = 'page';
var $last_row_param = 'last_row';
var $page_size_param = 'page_size';
var $other_params = array(); // array of parameters that are added to all URLs
function Pager(&$datasource) {
$this->datasource = &$datasource;
}
function processRequest() {
if (isset($_GET[$this->last_row_param])) {
$this->current_page = intval($_GET[$this->page_param]);
} else {
$this->current_page = $this->first_page;
}
if (isset($_GET[$this->last_row_param])) {
$this->last_row = intval($_GET[$this->last_row_param]);
} else {
$this->last_row = $this->datasource->getNumRows();
}
if (isset($_GET[$this->page_size_param])) {
$this->page_size = intval($_GET[$this->page_size_param]);
}
$this->setCurrentPage($this->current_page);
}
function setPageSize($n) {
if ($n > 0) {
$this->page_size = $n;
}
}
function setRangeSize($n) {
if ($n > 2) {
$this->range_size = $n;
}
}
function setCurrentPage($n) {
if ($this->last_row < 0) { // do not access datasource if last_rows provided
$this->last_row = $this->datasource->getNumRows();
}
if ($this->last_row > 0) {
$this->last_page = ceil($this->last_row / $this->page_size);
if ($n < $this->first_page) {
$n = $this->first_page;
}
if ($n > $this->last_page) {
$n = $this->last_page;
}
$this->current_page = $n;
$this->start_row = ($n - 1) * $this->page_size + 1;
$this->end_row = $this->start_row + $this->page_size - 1;
if ($this->end_row > $this->last_row) {
$this->end_row = $this->last_row;
}
} else {
$this->last_page = 0;
$this->current_page = 0;
$this->start_row = 0;
$this->end_row = 0;
}
}
function getPageSize() {
return $this->page_size;
}
function getCurrentPage() {
return $this->current_page;
}
function getLastPage() {
return $this->last_page;
}
function getFirstPage() {
return $this->first_page;
}
function getFirstRow() {
return $this->first_row;
}
function getLastRow() {
return $this->last_row;
}
function getStartRow() {
return $this->start_row;
}
function getEndRow() {
return $this->end_row;
}
function getValues() {
return array(
'page_size' => $this->page_size,
'page_size' => $this->last_page,
'current_page' => $this->current_page,
'start_row' => $this->start_row,
'end_row' => $this->end_row,
'last_row' => $this->last_row,
);
}
function getRange() {
// get number of links each side of current page
$side_size = floor($this->range_size / 2);
$range_start = $this->current_page - $side_size;
$range_end = $range_start + $this->range_size - 1;
// bounds check lower side of range
if ($range_start < $this->first_page) {
$range_start = $this->first_page;
}
if ($range_end > $this->last_page) {
$range_end = $this->last_page;
}
return range($range_start, $range_end);
}
}
class PagerHTMLWriter {
var $pager = null;
var $no_current_link = true; // no link for current page
function PagerHTMLWriter(&$pager) {
$this->pager = &$pager;
}
function getPageParams() {
$params = $this->pager->other_params;
$params[$this->pager->last_row_param] = $this->pager->last_row;
$params[$this->pager->page_size_param] = $this->pager->page_size;
return $params;
}
function getPageURL($n) {
if (($n > 0) && ($n <= $this->pager->last_page)) {
$params = $this->getPageParams();
foreach ($params as $name => $value) {
$param_strs[$name] = $name . '=' . $value;
}
$param_strs[$this->pager->page_param] = $this->pager->page_param . '=' . $n;
$url = $this->pager->page_url . '?' . implode('&', $param_strs);
} else {
$url = '';
}
return $url;
}
function getPageLink($n, $text='', $attrs='') {
if (($n > 0) && ($n <= $this->pager->last_page)) {
$str = ($text ? $text : $n);
if ($this->no_current_link && ($n ==$this->pager->current_page)) {
$link = $str;
} else {
$link = '<a href="' . $this->getPageURL($n) . "\" $attrs>" . $str . '</a>';
}
} else {
$link = '';
}
return $link;
}
function getPrevURL() {
if ($this->pager->current_page > $this->pager->first_page) {
$url = $this->getPageURL($this->pager->current_page - 1);
} else {
$url = '';
}
return $url;
}
function getNextURL() {
if ($this->pager->current_page < $this->pager->last_page) {
$url = $this->getPageURL($this->pager->current_page + 1);
} else {
$url = '';
}
return $url;
}
function getFirstURL() {
return $this->getPageURL($this->pager->first_page);
}
function getLastURL() {
return $this->getPageURL($this->pager->last_page);
}
function getRangeURLs() {
foreach ($this->pager->getRange() as $n) {
$urls[$n] = $this->getPageURL($n);
}
return $urls;
}
function getRangeLinks($attrs='') {
foreach ($this->pager->getRange() as $n) {
$links[$n] = $this->getPageLink($n, $attrs);
}
return $links;
}
function getPrevLink($text='Prev', $attrs='') {
if ($this->pager->current_page > $this->pager->first_page) {
$url = $this->getPageLink($this->pager->current_page - 1, $text, $attrs);
} else {
$url = '';
}
return $url;
}
function getNextLink($text='Next', $attrs='') {
if ($this->pager->current_page < $this->pager->last_page) {
$url = $this->getPageLink($this->pager->current_page + 1, $text, $attrs);
} else {
$url = '';
}
return $url;
}
function getFirstLink($text='First', $attrs='') {
return $this->getPageLink($this->pager->first_page, $text, $attrs);
}
function getLastLink($text='Last', $attrs='') {
return $this->getPageLink($this->pager->last_page, $text, $attrs);
}
}
Here is the PagerHTMLWriterJump.php file that creates <select> based paging:
Code: Select all
class PagerHTMLWriterJump extends PagerHTMLWriter {
var $current_page_template = 'Current Page {current_page}';
var $page_template = 'Page {current_page} of {last_page}';
function PagerHTMLWriterJump(&$pager) {
$this->PagerHTMLWriter($pager);
}
function setCurrentPageTemplate($template) {
$this->current_page_template = $template;
}
function setPageTemplate($template) {
$this->page_template = $template;
}
function createPagination($form_attr='', $submit_attr='', $option_attr='') {
$output = "<form action=\"\" method=\"GET\" $form_attr>\n";
$params = $this->getPageParams();
foreach ($params as $name => $value) {
$output .= "<input type=\"hidden\" name=\"$name\" value=\"$value\" />\n";
}
$output .= '<select name="'. $this->pager->page_param . "\" onChange=\"this.form.submit()\" $submit_attr>\n";
for ($i=1; $i<=$this->pager->last_page; ++$i) {
if ($i == $this->pager->current_page) {
$template = str_replace('{current_page}', $i, $this->current_page_template);
$output .= "<option value=\"$i\" selected=\"selected\" $option_attr>$template</option>\n";
} else {
$template = str_replace(array('{current_page}', '{last_page}'), array($i, $this->pager->last_page), $this->page_template);
$output .= "<option value=\"$i\" $option_attr>$template</option>\n";
}
}
$output .= "</select>\n</form>\n";
return $output;
}
}
Here is example code using the above fiels:
Code: Select all
include 'PageableArray.php';
// initialize an array to testing
for ($i=0; $i<=75; ++$i) {
$myarray[$i] = 'This is row ' . $i;
}
// create a data object that has the interface needed by the Pager object
$datasource = & new PageableArray($myarray);
include 'Pager.php';
// create pager using values from datasource and request params
$pager = & new Pager($datasource);
$pager->setRangeSize(5);
$pager->processRequest();
$writer = & new PagerHTMLWriter($pager);
echo $writer->getPrevLink() . ' | ' . implode(' | ', $writer->getRangeLinks()) . ' | ' . $writer->getNextLink() . '<p/>';
include 'PagerHTMLWriterJump.php';
$jump = & new PagerHTMLWriterJump($pager);
echo $jump->createPagination();