<?php
// +----------------------------------------------------------------------+
// | PHP version 4.0 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Stanislav Okhvat <stanis@ngs.ru> |
// +----------------------------------------------------------------------+
//
// $Id: PageNavigator.php, v 1.00 2002/02/20 11:40:00 stasokhvat Exp $
/**
* PageNavigator is a base class for creating page views that allow navigation
* of long data sets that span multiple pages.
*
* @author Stanislav Okhvat <stanis@ngs.ru>
* @version $Id: PageNavigator.php,v 1.00 2002/02/20 11:40:00 stasokhvat Exp $
* @package PageNavigator
* @access public
*/
class PageNavigator
{
/**
* Number of the current page.
*
* @var integer
* @access private
*/
var $current_page;
/**
* Number of records per one page.
*
* @var integer
* @access private
*/
var $records_per_page;
/**
* Total records in the data set.
*
* @var integer
* @access private
*/
var $total_records = 0;
/**
* Processed query string.
*
* @var integer
* @access private
*/
var $processed_query;
/**
* Number of pages. This is a cached copy.
*
* @var integer
* @access private
*/
var $totalpages;
/**
* Number of page to start with.
*
* @var integer
* @access private
*/
var $startpage;
/**
* Number of page to end with.
*
* @var integer
* @access private
*/
var $endpage;
/**
* Specifies which parameters go into produced query strings.
*
* @var array
* @access private
*/
var $query_vars;
/**
* String to print instead of a link / navigation label if there is none.
*
* @var string
* @access private
*/
var $empty_cell = '<td> </td>';
/**
* Constructor. Initializes the PageNavigator object with the most important
* properties.
*
* @param integer current page number
* @param integer number of records per one page
* @param integer total records. May be initialized later.
* @return void
* @access public
*/
function PageNavigator($current_page=0, $records_per_page=15, $total_records=0, $query_vars='')
{
$this->setCurrentPage($current_page);
$this->setRecordsPerPage($records_per_page);
$this->setRecordCount($total_records);
$this->setQueryVars($query_vars);
} // end func PageNavigator
/**
* Sets the number of records to span.
*
* @param integer number of records in data set
* @return void
* @access public
*/
function setRecordCount($rec_num)
{
$this->total_records = $rec_num;
}
/**
* Returns the number of records to span.
*
* @return integer
* @access public
*/
function getRecordCount()
{
return $this->total_records;
}
/**
* Sets the current page.
*
* @param integer current page
* @return void
* @access public
*/
function setCurrentPage($current_page)
{
if (empty($current_page) || $current_page <= 0) $current_page = 1;
$this->current_page = $current_page;
}
/**
* Returns the current page.
*
* @return integer current page
* @access public
*/
function getCurrentPage()
{
return $this->current_page;
}
/**
* Sets records per page.
*
* @param integer records per page
* @return void
* @access public
*/
function setRecordsPerPage($records_per_page)
{
$this->records_per_page = $records_per_page;
}
/**
* Returns records per page.
*
* @return integer records per page
* @access public
*/
function getRecordsPerPage()
{
return $this->records_per_page;
}
/**
* Returns total number of pages using number of records and
* records per page (already saved to object member variables).
*
* @return integer total number of pages
* @access public
*/
function getTotalPages()
{
return ceil($this->total_records / $this->records_per_page);
}
/**
* Sets query string variables to purge from / save to target query string
*
* @return void
* @access public
*/
function setQueryVars($vars='')
{
if (!is_array($vars)) $vars = array('page'=>'page');
$this->query_vars = $vars;
} // end func setQueryVars
/**
* Returns the start and end record for the given page by reference.
*
* @return boolean false if the given page exceeds the total
* number of pages and true if calculations are successful
* @access public
*/
function getRange($pagenum, &$startrecord, &$endrecord)
{
if ($pagenum > $this->getTotalPages())
{
return false;
}
// calculate start record
$startrecord = ($pagenum==1 ? 1 : (($pagenum - 1) * $this->records_per_page) + 1);
// calculate end record
$endrecord = $startrecord + $this->records_per_page - 1; // initial
if ($endrecord > $this->total_records)
$endrecord = $this->total_records; // fix if out of bounds
return true;
} // end func getRange
/**
* Returns the page number given the start record and number of records
* per one page
*
* @return integer page number that corresponds to the passed parameters
* @access public
*/
function toPage($startrec, $records_per_page)
{
$page = ($startrec > 0 ? ceil($startrec / $records_per_page) : 1);
return $page;
} // end func toPage
/*
* METHODS TO OVERRIDE IN CUSTOM CLASSES
*/
function preCalculateParameters()
{
$this->totalpages = $this->startpage = $this->endpage = 0;
}
function render()
{
die('PageNavigator::Render needs to be overridden.');
}
function formatActivePage($pagenum)
{
return "<td nowrap><b>$pagenum</b></td>\n";
}
function formatPage($pagenum)
{
return "<td nowrap><a href=\"".
$this->getTargetUrl($pagenum)."\">$pagenum</a></td>\n";
}
function formatMovePrevious($pagenum)
{
return "<td nowrap><a href=\"".$this->getTargetUrl($pagenum)."\"><</a></td>\n";
}
function formatMoveNext($pagenum)
{
return "<td nowrap><a href=\"".$this->getTargetUrl($pagenum)."\">></a></td>\n";
}
function formatMovePrevSet($pagenum)
{
return "<td nowrap><a href=\"".$this->getTargetUrl($pagenum)."\"><<</a></td>\n";
}
function formatMoveNextSet($pagenum)
{
return "<td nowrap><a href=\"".$this->getTargetUrl($pagenum)."\">>></a></td>\n";
}
function formatHeader()
{
return "<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\">\n<tr valign=\"top\">";
}
function formatFooter()
{
return "</tr>\n</table>\n";
}
/*
* PRIVATE UTILITY METHODS
*/
/**
* Counts results contained in an sql query by constructing
* a special sql query from given params and executing it
* against the database identifier (uses PHPLIB)
*
* @param resource database resource identifier
* @param string if $tablejoin_valid is false, this is the entire
* SQL statement. If $tablejoin_valid is true,
* this is only the entire valid table join.
* @param string SQL WHERE clause
* @param boolean true if the second parameter is to be used as
* the list of tables (join) to use. False if
* the second parameter is to be used as the entire
* SQL statement.
*
* @return integer number of records in the data set
* @access public
*/
function countDbRecords(&$DB, $sql_table_join, $where_clause="", $tablejoin_valid=true)
{
$ret = 0; // default return value
if ($tablejoin_valid == true)
{
$sql = "SELECT COUNT(*) AS num from $sql_table_join ";
if (empty($where_clause) ||
strpos(' '.strtolower($where_clause), 'where') == 0)
{
$sql .= "WHERE ";
}
$sql .= $where_clause;
}
else
{
$sql = $sql_table_join;
}
$query = new query($DB, $sql);
$row = $query->getrow();
if (is_array($row))
{
$ret = (int)$row['num'];
}
$query->free();
return $ret;
} // end func countDbRecords
/**
* Automatically loads and sets current page variables within PageNavigator.
*
* @return void
* @access public
*/
function autoLoadFromQuery()
{
if (is_array($this->query_vars))
{
if (isset($this->query_vars['page']))
{
$var = $this->query_vars['page'];
global $$var;
$this->setCurrentPage($$var);
}
elseif (isset($this->query_vars['from']))
{
// adjust records per page if necessary
if (isset($this->query_vars['count']))
{
$var = $this->query_vars['count'];
global $$var;
$this->setRecordsPerPage($$var);
}
// load current page
$var = $this->query_vars['from'];
global $$var;
$this->setCurrentPage(
$this->toPage($$var, $this->getRecordsPerPage())
);
}
}
} // end func autoLoadFromQuery
/**
* Clears the query string of all variables that are needed
* by this class (i.e. $page or $from/$to, $from/$num) and returns it.
*
* @param array array of strings identifying variables that need to be stripped from the current URI query string
* @return string stripped query string
* @access public
*/
function getStrippedQueryString($vars_array)
{
global $HTTP_GET_VARS;
$query_vars = $HTTP_GET_VARS;
// strip control variables
foreach ($vars_array as $v)
{
unset($query_vars[$v]);
}
$qr = '';
foreach ($query_vars as $k=>$v)
{
$qr .= $k.'='.urlencode($v).'&';
}
if (!empty($qr)) $qr = substr($qr, 0, -1);
return $qr;
} // end func getStrippedQueryString
/**
* Returns the link to jump to.
*
* @return string target link
* @access private
*/
function getTargetUrl($pagenum)
{
global $PHP_SELF;
$query_str = $this->processed_query;
if (!empty($query_str))
{
$query_str .= "&";
}
return $PHP_SELF."?".$query_str.$this->prepareQueryVars($pagenum);
} // end func getTargetUrl
/**
* Returns a string to be inserted into the URL to switch pages
* (i.e. page=2 or start=11&limit=10, etc). Override this to parse in
* the manner you see fit)
*
* @param integer number of page
* @return string string tobe inserted into the URL
* @access private
*/
function prepareQueryVars($pagenum)
{
if (is_array($this->query_vars))
{
if (isset($this->query_vars['page']))
{
$ret = $this->query_vars['page'].'='.$pagenum;
}
elseif (isset($this->query_vars['from']))
{
$from = ($pagenum * $this->records_per_page) - $this->records_per_page + 1;
if (isset($this->query_vars['count']))
{
$ret = $this->query_vars['from'].'='.$from.'&'.
$this->query_vars['count'].'='.
$this->records_per_page;
}
else
{
$ret = $this->query_vars['from'].'='.$from;
}
}
}
return $ret;
} // end func prepareQueryVars
/**
* Caches the copy of the query string, first purging it of all variables
* like page, from, to, etc, depending on what the developer intends to do
*
* @return void
* @access private
*/
function setProcessedQueryString()
{
$this->processed_query =
$this->getStrippedQueryString($this->query_vars);
} // end func setProcessedQueryString
} // end class PageNavigator
?> |