3 // Pear DB Pager - Retrieve and return information of databases
6 // Copyright (C) 2001 Tomas Von Veschler Cox <cox@idecnet.com>
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 require_once 'PEAR.php';
26 require_once 'DB.php';
29 * This class handles all the stuff needed for displaying paginated results
30 * from a database query of Pear DB, in a very easy way.
31 * Documentation and examples of use, can be found in:
32 * http://vulcanonet.com/soft/pager/ (could be outdated)
35 * Since PEAR DB already support native row limit (more fast and avaible in
36 * all the drivers), there is no more need to use $pager->build() or
37 * the $pager->fetch*() methods.
42 * require_once 'DB/Pager.php';
43 * $db = DB::connect('your DSN string');
44 * $from = 0; // The row to start to fetch from (you might want to get this
45 * // param from the $_GET array
46 * $limit = 10; // The number of results per page
47 * $maxpages = 10; // The number of pages for displaying in the pager (optional)
48 * $res = $db->limitQuery($sql, $from, $limit);
49 * $nrows = 0; // Alternative you could use $res->numRows()
50 * while ($row = $res->fetchrow()) {
51 * // XXX code for building the page here
54 * $data = DB_Pager::getData($from, $limit, $nrows, $maxpages);
55 * // XXX code for building the pager here
59 * @author Tomas V.V.Cox <cox@idecnet.com>
60 * @see http://vulcanonet.com/soft/pager/
63 class MECON_DB_Pager extends DB_Result
69 * Gets all the data needed to paginate results
70 * The object has this properties:
72 * 'current' => X, // current page you are
73 * 'numrows' => X, // total number of results
74 * 'next' => X, // row number where next page starts
75 * 'prev' => X, // row number where prev page starts
76 * 'remain' => X, // number of results remaning *in next page*
77 * 'numpages'=> X, // total number of pages
78 * 'from' => X, // the row to start fetching
79 * 'to' => X, // the row to stop fetching
80 * 'limit' => X, // how many results per page
81 * 'maxpages' => X, // how many pages to show (google style)
82 * 'firstpage' => X, // the row number of the first page
83 * 'lastpage' => X, // the row number where the last page starts
84 * 'pages' => array( // assoc with page "number => start row"
91 * @param object $res A DB_result object from Pear_DB
92 * @param int $from The row to start fetching
93 * @param int $limit How many results per page
94 * @param int $maxpages Maximum pages to display
95 * @param int $numrows Pager will automatically
96 * find this param if is not given. If your Pear_DB backend extension
97 * doesn't support numrows(), you can manually calculate it
98 * and supply later to the constructor
101 function MECON_DB_Pager (&$res, $from = 0, $limit = 10, $maxpages = 21, $numrows = null)
103 $this->dbh = $res->dbh;
104 $this->result = $res->result;
105 $this->row_counter = $res->row_counter;
106 $this->limit_from = $res->limit_from;
108 $this->limit = $limit;
109 $this->numrows = $numrows;
110 $this->maxpages = $maxpages;
115 * Calculates all the data needed by Pager to work
116 * @return mixed PEAR_Error if error.
120 // if there is no numrows given, calculate it
121 if ($this->numrows === null) {
122 $this->numrows = $this->numrows();
123 if (DB::isError($this->numrows)) {
124 return $this->numrows;
127 // Si no hay resultados no se hace nada.
128 if (empty($this->numrows) or ($this->numrows < 0)) {
131 $this->from = empty($this->from) ? 0 : $this->from;
133 if ($this->limit <= 0) {
134 return PEAR::raiseError (null, 'wrong "limit" param', null,
135 null, null, 'DB_Error', true);
138 // Total number of pages
139 $this->numpages = ceil($this->numrows/$this->limit);
142 $this->firstpage = 1;
143 $this->lastpage = $this->numpages;
146 $this->pages = array();
147 for ($i = 1; $i <= $this->numpages; $i++) {
148 $offset = $this->limit * ($i - 1);
149 $this->pages[$i] = $offset;
150 // $from must point to one page
151 if ($this->from == $offset) {
152 // The current page we are
153 $this->currentpage = $i;
156 if (!isset($this->currentpage)) {
157 return PEAR::raiseError (null, 'wrong "from" param', null,
158 null, null, 'DB_Error', true);
161 // Limit number of pages (goole algoritm)
162 if ($this->maxpages) {
163 $radio = floor($this->maxpages/2);
164 $this->firstpage = $this->currentpage - $radio;
165 if (!($this->maxpages % 2)) {
168 if ($this->firstpage < 1) {
169 $this->firstpage = 1;
171 $this->lastpage = $this->currentpage + $radio;
172 if ($this->lastpage > $this->numpages) {
173 $this->lastpage = $this->numpages;
175 foreach (range($this->firstpage, $this->lastpage) as $page) {
176 $tmp[$page] = $this->pages[$page];
182 $this->prev = $this->from - $this->limit;
183 $this->prev = ($this->prev >= 0) ? $this->prev : null;
186 $this->next = $this->from + $this->limit;
187 $this->next = ($this->next < $this->numrows) ? $this->next : null;
189 // Results remaining in next page & Last row to fetch
190 if ($this->currentpage == $this->numpages) {
192 $this->to = $this->numrows;
194 if ($this->currentpage == ($this->numpages - 1)) {
195 $this->remain = $this->numrows - ($this->limit * ($this->numpages - 1));
197 $this->remain = $this->limit;
199 $this->to = $this->currentpage * $this->limit;
202 // Current item (when fetching).
203 $this->current = $this->from - 1;
206 function fetchRow($mode=DB_FETCHMODE_DEFAULT, $rownum=null)
209 if ($this->current >= $this->to) {
212 return parent::fetchRow($mode, $this->current);
215 function fetchInto(&$arr, $mode=DB_FETCHMODE_DEFAULT)
218 if ($this->current >= $this->to) {
221 return parent::fetchInto($arr, $mode, $this->current);