1<?php
2
3/*
4	v4.992 10 Nov 2009  (c) 2000-2009 John Lim (jlim#natsoft.com). All rights reserved.
5	  Released under both BSD license and Lesser GPL library license.
6	  Whenever there is any discrepancy between the two licenses,
7	  the BSD license will take precedence.
8	  Set tabs to 4 for best viewing.
9
10  	This class provides recordset pagination with
11	First/Prev/Next/Last links.
12
13	Feel free to modify this class for your own use as
14	it is very basic. To learn how to use it, see the
15	example in adodb/tests/testpaging.php.
16
17	"Pablo Costa" <pablo@cbsp.com.br> implemented Render_PageLinks().
18
19	Please note, this class is entirely unsupported,
20	and no free support requests except for bug reports
21	will be entertained by the author.
22
23*/
24class ADODB_Pager {
25	var $id; 	// unique id for pager (defaults to 'adodb')
26	var $db; 	// ADODB connection object
27	var $sql; 	// sql used
28	var $rs;	// recordset generated
29	var $curr_page;	// current page number before Render() called, calculated in constructor
30	var $rows;		// number of rows per page
31    var $linksPerPage=10; // number of links per page in navigation bar
32    var $showPageLinks;
33
34	var $gridAttributes = 'width=100% border=1 bgcolor=white';
35
36	// Localize text strings here
37	var $first = '<code>|&lt;</code>';
38	var $prev = '<code>&lt;&lt;</code>';
39	var $next = '<code>>></code>';
40	var $last = '<code>>|</code>';
41	var $moreLinks = '...';
42	var $startLinks = '...';
43	var $gridHeader = false;
44	var $htmlSpecialChars = true;
45	var $page = 'Page';
46	var $linkSelectedColor = 'red';
47	var $cache = 0;  #secs to cache with CachePageExecute()
48
49	//----------------------------------------------
50	// constructor
51	//
52	// $db	adodb connection object
53	// $sql	sql statement
54	// $id	optional id to identify which pager,
55	//		if you have multiple on 1 page.
56	//		$id should be only be [a-z0-9]*
57	//
58	function ADODB_Pager(&$db,$sql,$id = 'adodb', $showPageLinks = false)
59	{
60	global $PHP_SELF;
61
62		$curr_page = $id.'_curr_page';
63		$PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']); // htmlspecialchars() to prevent XSS attacks
64
65		$this->sql = $sql;
66		$this->id = $id;
67		$this->db = $db;
68		$this->showPageLinks = $showPageLinks;
69
70		$next_page = $id.'_next_page';
71
72		if (isset($_GET[$next_page])) {
73			$_SESSION[$curr_page] = (integer) $_GET[$next_page];
74		}
75		if (empty($_SESSION[$curr_page])) $_SESSION[$curr_page] = 1; ## at first page
76
77		$this->curr_page = $_SESSION[$curr_page];
78
79	}
80
81	//---------------------------
82	// Display link to first page
83	function Render_First($anchor=true)
84	{
85	global $PHP_SELF;
86		if ($anchor) {
87	?>
88		<a href="<?php echo $PHP_SELF,'?',$this->id;?>_next_page=1"><?php echo $this->first;?></a> &nbsp;
89	<?php
90		} else {
91			print "$this->first &nbsp; ";
92		}
93	}
94
95	//--------------------------
96	// Display link to next page
97	function render_next($anchor=true)
98	{
99	global $PHP_SELF;
100
101		if ($anchor) {
102		?>
103		<a href="<?php echo $PHP_SELF,'?',$this->id,'_next_page=',$this->rs->AbsolutePage() + 1 ?>"><?php echo $this->next;?></a> &nbsp;
104		<?php
105		} else {
106			print "$this->next &nbsp; ";
107		}
108	}
109
110	//------------------
111	// Link to last page
112	//
113	// for better performance with large recordsets, you can set
114	// $this->db->pageExecuteCountRows = false, which disables
115	// last page counting.
116	function render_last($anchor=true)
117	{
118	global $PHP_SELF;
119
120		if (!$this->db->pageExecuteCountRows) return;
121
122		if ($anchor) {
123		?>
124			<a href="<?php echo $PHP_SELF,'?',$this->id,'_next_page=',$this->rs->LastPageNo() ?>"><?php echo $this->last;?></a> &nbsp;
125		<?php
126		} else {
127			print "$this->last &nbsp; ";
128		}
129	}
130
131	//---------------------------------------------------
132	// original code by "Pablo Costa" <pablo@cbsp.com.br>
133        function render_pagelinks()
134        {
135        global $PHP_SELF;
136            $pages        = $this->rs->LastPageNo();
137            $linksperpage = $this->linksPerPage ? $this->linksPerPage : $pages;
138            for($i=1; $i <= $pages; $i+=$linksperpage)
139            {
140                if($this->rs->AbsolutePage() >= $i)
141                {
142                    $start = $i;
143                }
144            }
145			$numbers = '';
146            $end = $start+$linksperpage-1;
147			$link = $this->id . "_next_page";
148            if($end > $pages) $end = $pages;
149
150
151			if ($this->startLinks && $start > 1) {
152				$pos = $start - 1;
153				$numbers .= "<a href=$PHP_SELF?$link=$pos>$this->startLinks</a>  ";
154            }
155
156			for($i=$start; $i <= $end; $i++) {
157                if ($this->rs->AbsolutePage() == $i)
158                    $numbers .= "<font color=$this->linkSelectedColor><b>$i</b></font>  ";
159                else
160                     $numbers .= "<a href=$PHP_SELF?$link=$i>$i</a>  ";
161
162            }
163			if ($this->moreLinks && $end < $pages)
164				$numbers .= "<a href=$PHP_SELF?$link=$i>$this->moreLinks</a>  ";
165            print $numbers . ' &nbsp; ';
166        }
167	// Link to previous page
168	function render_prev($anchor=true)
169	{
170	global $PHP_SELF;
171		if ($anchor) {
172	?>
173		<a href="<?php echo $PHP_SELF,'?',$this->id,'_next_page=',$this->rs->AbsolutePage() - 1 ?>"><?php echo $this->prev;?></a> &nbsp;
174	<?php
175		} else {
176			print "$this->prev &nbsp; ";
177		}
178	}
179
180	//--------------------------------------------------------
181	// Simply rendering of grid. You should override this for
182	// better control over the format of the grid
183	//
184	// We use output buffering to keep code clean and readable.
185	function RenderGrid()
186	{
187	global $gSQLBlockRows; // used by rs2html to indicate how many rows to display
188		include_once(ADODB_DIR.'/tohtml.inc.php');
189		ob_start();
190		$gSQLBlockRows = $this->rows;
191		rs2html($this->rs,$this->gridAttributes,$this->gridHeader,$this->htmlSpecialChars);
192		$s = ob_get_contents();
193		ob_end_clean();
194		return $s;
195	}
196
197	//-------------------------------------------------------
198	// Navigation bar
199	//
200	// we use output buffering to keep the code easy to read.
201	function RenderNav()
202	{
203		ob_start();
204		if (!$this->rs->AtFirstPage()) {
205			$this->Render_First();
206			$this->Render_Prev();
207		} else {
208			$this->Render_First(false);
209			$this->Render_Prev(false);
210		}
211        if ($this->showPageLinks){
212            $this->Render_PageLinks();
213        }
214		if (!$this->rs->AtLastPage()) {
215			$this->Render_Next();
216			$this->Render_Last();
217		} else {
218			$this->Render_Next(false);
219			$this->Render_Last(false);
220		}
221		$s = ob_get_contents();
222		ob_end_clean();
223		return $s;
224	}
225
226	//-------------------
227	// This is the footer
228	function RenderPageCount()
229	{
230		if (!$this->db->pageExecuteCountRows) return '';
231		$lastPage = $this->rs->LastPageNo();
232		if ($lastPage == -1) $lastPage = 1; // check for empty rs.
233		if ($this->curr_page > $lastPage) $this->curr_page = 1;
234		return "<font size=-1>$this->page ".$this->curr_page."/".$lastPage."</font>";
235	}
236
237	//-----------------------------------
238	// Call this class to draw everything.
239	function Render($rows=10)
240	{
241	global $ADODB_COUNTRECS;
242
243		$this->rows = $rows;
244
245		if ($this->db->dataProvider == 'informix') $this->db->cursorType = IFX_SCROLL;
246
247		$savec = $ADODB_COUNTRECS;
248		if ($this->db->pageExecuteCountRows) $ADODB_COUNTRECS = true;
249		if ($this->cache)
250			$rs = &$this->db->CachePageExecute($this->cache,$this->sql,$rows,$this->curr_page);
251		else
252			$rs = &$this->db->PageExecute($this->sql,$rows,$this->curr_page);
253		$ADODB_COUNTRECS = $savec;
254
255		$this->rs = &$rs;
256		if (!$rs) {
257			print "<h3>Query failed: $this->sql</h3>";
258			return;
259		}
260
261		if (!$rs->EOF && (!$rs->AtFirstPage() || !$rs->AtLastPage()))
262			$header = $this->RenderNav();
263		else
264			$header = "&nbsp;";
265
266		$grid = $this->RenderGrid();
267		$footer = $this->RenderPageCount();
268
269		$this->RenderLayout($header,$grid,$footer);
270
271		$rs->Close();
272		$this->rs = false;
273	}
274
275	//------------------------------------------------------
276	// override this to control overall layout and formating
277	function RenderLayout($header,$grid,$footer,$attributes='border=1 bgcolor=beige')
278	{
279		echo "<table ".$attributes."><tr><td>",
280				$header,
281			"</td></tr><tr><td>",
282				$grid,
283			"</td></tr><tr><td>",
284				$footer,
285			"</td></tr></table>";
286	}
287}
288
289
290?>