]> git.llucax.com Git - mecon/meconlib.git/blob - lib/MECON/DB/Pager.php
Se mejora un poco los ALT para navegadores de texto.
[mecon/meconlib.git] / lib / MECON / DB / Pager.php
1 <?php
2 //
3 //  Pear DB Pager - Retrieve and return information of databases
4 //                  result sets
5 //
6 //  Copyright (C) 2001  Tomas Von Veschler Cox <cox@idecnet.com>
7 //
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.
12 //
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.
17 //
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
21 //
22 //
23 // $Id$
24
25 require_once 'PEAR.php';
26 require_once 'DB.php';
27
28 /**
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)
33 *
34 * IMPORTANT!
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.
38 *
39 * Usage example:
40 *
41 *< ?php
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
52 *     $nrows++;
53 * }
54 * $data = DB_Pager::getData($from, $limit, $nrows, $maxpages);
55 * // XXX code for building the pager here
56 * ? >
57 *
58 * @version 0.7
59 * @author Tomas V.V.Cox <cox@idecnet.com>
60 * @see http://vulcanonet.com/soft/pager/
61 */
62
63 class MECON_DB_Pager extends DB_Result
64 {
65
66     var $currentpage = 0;
67     var $current = 0;
68     var $to = 0;
69
70     /**
71     * Constructor
72     *
73     * Gets all the data needed to paginate results
74     * The object has this properties:
75     *
76     *    'current' => X,    // current page you are
77     *    'numrows' => X,    // total number of results
78     *    'next'    => X,    // row number where next page starts
79     *    'prev'    => X,    // row number where prev page starts
80     *    'remain'  => X,    // number of results remaning *in next page*
81     *    'numpages'=> X,    // total number of pages
82     *    'from'    => X,    // the row to start fetching
83     *    'to'      => X,    // the row to stop fetching
84     *    'limit'   => X,    // how many results per page
85     *    'maxpages'   => X, // how many pages to show (google style)
86     *    'firstpage'  => X, // the row number of the first page
87     *    'lastpage'   => X, // the row number where the last page starts
88     *    'pages'   => array(    // assoc with page "number => start row"
89     *                1 => X,
90     *                2 => X,
91     *                3 => X
92     *                )
93     *    );
94
95     * @param object $res  A DB_result object from Pear_DB
96     * @param int    $from  The row to start fetching
97     * @param int    $limit  How many results per page
98     * @param int    $maxpages  Maximum pages to display
99     * @param int    $numrows Pager will automatically
100     *    find this param if is not given. If your Pear_DB backend extension
101     *    doesn't support numrows(), you can manually calculate it
102     *    and supply later to the constructor
103     * @deprecated
104     */
105     function MECON_DB_Pager (&$res, $from = 0, $limit = 10, $maxpages = 21, $numrows = null)
106     {
107         $this->dbh = $res->dbh;
108         $this->result = $res->result;
109         $this->row_counter = $res->row_counter;
110         $this->limit_from = $res->limit_from;
111         $this->from = $from;
112         $this->limit = $limit;
113         $this->numrows = $numrows;
114         $this->maxpages = $maxpages;
115         $this->build();
116     }
117
118     /**
119     * Calculates all the data needed by Pager to work
120     * @return mixed PEAR_Error if error.
121     */
122     function build()
123     {
124         // if there is no numrows given, calculate it
125         if ($this->numrows === null) {
126             $this->numrows = $this->numrows();
127             if (DB::isError($this->numrows)) {
128                 return $this->numrows;
129             }
130         }
131         // Si no hay resultados no se hace nada.
132         if (empty($this->numrows) or ($this->numrows < 0)) {
133             return;
134         }
135         $this->from = empty($this->from) ? 0 : $this->from;
136
137         if ($this->limit <= 0) {
138             return PEAR::raiseError (null, 'wrong "limit" param', null,
139                                      null, null, 'DB_Error', true);
140         }
141
142         // Total number of pages
143         $this->numpages = ceil($this->numrows/$this->limit);
144
145         // first & last page
146         $this->firstpage = 1;
147         $this->lastpage  = $this->numpages;
148
149         // Build pages array
150         $this->pages = array();
151         for ($i = 1; $i <= $this->numpages; $i++) {
152             $offset = $this->limit * ($i - 1);
153             $this->pages[$i] = $offset;
154             // $from must point to one page
155             if ($this->from == $offset) {
156                 // The current page we are
157                 $this->currentpage = $i;
158             }
159         }
160         if (!isset($this->currentpage)) {
161             return PEAR::raiseError (null, 'wrong "from" param', null,
162                                      null, null, 'DB_Error', true);
163         }
164
165         // Limit number of pages (goole algoritm)
166         if ($this->maxpages) {
167             $radio = floor($this->maxpages/2);
168             $this->firstpage = $this->currentpage - $radio;
169             if (!($this->maxpages % 2)) {
170                 $this->firstpage++;
171             }
172             if ($this->firstpage < 1) {
173                 $this->firstpage = 1;
174             }
175             $this->lastpage = $this->currentpage + $radio;
176             if ($this->lastpage > $this->numpages) {
177                 $this->lastpage = $this->numpages;
178             }
179             foreach (range($this->firstpage, $this->lastpage) as $page) {
180                 $tmp[$page] = $this->pages[$page];
181             }
182             $this->pages = $tmp;
183         }
184
185         // Prev link
186         $this->prev = $this->from - $this->limit;
187         $this->prev = ($this->prev >= 0) ? $this->prev : null;
188
189         // Next link
190         $this->next = $this->from + $this->limit;
191         $this->next = ($this->next < $this->numrows) ? $this->next : null;
192
193         // Results remaining in next page & Last row to fetch
194         if ($this->currentpage == $this->numpages) {
195             $this->remain = 0;
196             $this->to = $this->numrows;
197         } else {
198             if ($this->currentpage == ($this->numpages - 1)) {
199                 $this->remain = $this->numrows - ($this->limit * ($this->numpages - 1));
200             } else {
201                 $this->remain = $this->limit;
202             }
203             $this->to = $this->currentpage * $this->limit;
204         }
205
206         // Current item (when fetching).
207         $this->current = $this->from - 1;
208     }
209
210     function fetchRow($mode=DB_FETCHMODE_DEFAULT, $rownum=null)
211     {
212         $this->current++;
213         if ($this->current >= $this->to) {
214             return null;
215         }
216         return parent::fetchRow($mode, $this->current);
217     }
218
219     function fetchInto(&$arr, $mode=DB_FETCHMODE_DEFAULT)
220     {
221         $this->current++;
222         if ($this->current >= $this->to) {
223             return null;
224         }
225         return parent::fetchInto($arr, $mode, $this->current);
226     }
227 }
228 ?>