// // 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. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // // $Id$ require_once 'PEAR.php'; require_once 'DB.php'; /** * This class handles all the stuff needed for displaying paginated results * from a database query of Pear DB, in a very easy way. * Documentation and examples of use, can be found in: * http://vulcanonet.com/soft/pager/ (could be outdated) * * IMPORTANT! * Since PEAR DB already support native row limit (more fast and avaible in * all the drivers), there is no more need to use $pager->build() or * the $pager->fetch*() methods. * * Usage example: * *< ?php * require_once 'DB/Pager.php'; * $db = DB::connect('your DSN string'); * $from = 0; // The row to start to fetch from (you might want to get this * // param from the $_GET array * $limit = 10; // The number of results per page * $maxpages = 10; // The number of pages for displaying in the pager (optional) * $res = $db->limitQuery($sql, $from, $limit); * $nrows = 0; // Alternative you could use $res->numRows() * while ($row = $res->fetchrow()) { * // XXX code for building the page here * $nrows++; * } * $data = DB_Pager::getData($from, $limit, $nrows, $maxpages); * // XXX code for building the pager here * ? > * * @version 0.7 * @author Tomas V.V.Cox * @see http://vulcanonet.com/soft/pager/ */ class MECON_DB_Pager extends DB_Result { var $currentpage = 0; var $current = 0; var $to = 0; /** * Constructor * * Gets all the data needed to paginate results * The object has this properties: * * 'current' => X, // current page you are * 'numrows' => X, // total number of results * 'next' => X, // row number where next page starts * 'prev' => X, // row number where prev page starts * 'remain' => X, // number of results remaning *in next page* * 'numpages'=> X, // total number of pages * 'from' => X, // the row to start fetching * 'to' => X, // the row to stop fetching * 'limit' => X, // how many results per page * 'maxpages' => X, // how many pages to show (google style) * 'firstpage' => X, // the row number of the first page * 'lastpage' => X, // the row number where the last page starts * 'pages' => array( // assoc with page "number => start row" * 1 => X, * 2 => X, * 3 => X * ) * ); * @param object $res A DB_result object from Pear_DB * @param int $from The row to start fetching * @param int $limit How many results per page * @param int $maxpages Maximum pages to display * @param int $numrows Pager will automatically * find this param if is not given. If your Pear_DB backend extension * doesn't support numrows(), you can manually calculate it * and supply later to the constructor * @deprecated */ function MECON_DB_Pager (&$res, $from = 0, $limit = 10, $maxpages = 21, $numrows = null) { $this->dbh = $res->dbh; $this->result = $res->result; $this->row_counter = $res->row_counter; $this->limit_from = $res->limit_from; $this->from = $from; $this->limit = $limit; $this->numrows = $numrows; $this->maxpages = $maxpages; $this->build(); } /** * Calculates all the data needed by Pager to work * @return mixed PEAR_Error if error. */ function build() { // if there is no numrows given, calculate it if ($this->numrows === null) { $this->numrows = $this->numrows(); if (DB::isError($this->numrows)) { return $this->numrows; } } // Si no hay resultados no se hace nada. if (empty($this->numrows) or ($this->numrows < 0)) { return; } $this->from = empty($this->from) ? 0 : $this->from; if ($this->limit <= 0) { return PEAR::raiseError (null, 'wrong "limit" param', null, null, null, 'DB_Error', true); } // Total number of pages $this->numpages = ceil($this->numrows/$this->limit); // first & last page $this->firstpage = 1; $this->lastpage = $this->numpages; // Build pages array $this->pages = array(); for ($i = 1; $i <= $this->numpages; $i++) { $offset = $this->limit * ($i - 1); $this->pages[$i] = $offset; // $from must point to one page if ($this->from == $offset) { // The current page we are $this->currentpage = $i; } } if (!isset($this->currentpage)) { return PEAR::raiseError (null, 'wrong "from" param', null, null, null, 'DB_Error', true); } // Limit number of pages (goole algoritm) if ($this->maxpages) { $radio = floor($this->maxpages/2); $this->firstpage = $this->currentpage - $radio; if (!($this->maxpages % 2)) { $this->firstpage++; } if ($this->firstpage < 1) { $this->firstpage = 1; } $this->lastpage = $this->currentpage + $radio; if ($this->lastpage > $this->numpages) { $this->lastpage = $this->numpages; } foreach (range($this->firstpage, $this->lastpage) as $page) { $tmp[$page] = $this->pages[$page]; } $this->pages = $tmp; } // Prev link $this->prev = $this->from - $this->limit; $this->prev = ($this->prev >= 0) ? $this->prev : null; // Next link $this->next = $this->from + $this->limit; $this->next = ($this->next < $this->numrows) ? $this->next : null; // Results remaining in next page & Last row to fetch if ($this->currentpage == $this->numpages) { $this->remain = 0; $this->to = $this->numrows; } else { if ($this->currentpage == ($this->numpages - 1)) { $this->remain = $this->numrows - ($this->limit * ($this->numpages - 1)); } else { $this->remain = $this->limit; } $this->to = $this->currentpage * $this->limit; } // Current item (when fetching). $this->current = $this->from - 1; } function fetchRow($mode=DB_FETCHMODE_DEFAULT, $rownum=null) { $this->current++; if ($this->current >= $this->to) { return null; } return parent::fetchRow($mode, $this->current); } function fetchInto(&$arr, $mode=DB_FETCHMODE_DEFAULT) { $this->current++; if ($this->current >= $this->to) { return null; } return parent::fetchInto($arr, $mode, $this->current); } } ?>