blob: cdec736ff9a6435a4e67f1a12407df516700bae5 [file] [log] [blame]
Andrey Andreev33987e62011-12-24 19:48:45 +02001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Phil Sturgeon07c1ac82012-03-09 17:03:37 +00005 * An open source application development framework for PHP 5.2.4 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Eric Barnes9a4902a2011-12-03 23:46:06 -05008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Eric Barnes9a4902a2011-12-03 23:46:06 -050010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Derek Allard2067d1a2008-11-13 22:59:24 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
Greg Aker0defe5d2012-01-01 18:46:41 -060021 * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
Derek Jonesf4a4bd82011-10-20 12:18:42 -050022 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
24 * @since Version 1.0
25 * @filesource
26 */
27
Derek Allard2067d1a2008-11-13 22:59:24 +000028/**
29 * Pagination Class
30 *
31 * @package CodeIgniter
32 * @subpackage Libraries
33 * @category Pagination
Derek Jonesf4a4bd82011-10-20 12:18:42 -050034 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000035 * @link http://codeigniter.com/user_guide/libraries/pagination.html
36 */
37class CI_Pagination {
38
Andrey Andreev7eb7ebf2012-06-12 10:26:27 +030039 public $base_url = ''; // The page we are linking to
40 public $prefix = ''; // A custom prefix added to the path.
41 public $suffix = ''; // A custom suffix added to the path.
42 public $total_rows = 0; // Total number of items (database results)
43 public $per_page = 10; // Max number of items you want shown per page
44 public $num_links = 2; // Number of "digit" links to show before/after the currently viewed page
45 public $cur_page = 0; // The current page being viewed
46 public $use_page_numbers = FALSE; // Use page number for segment instead of offset
47 public $first_link = '&lsaquo; First';
48 public $next_link = '&gt;';
49 public $prev_link = '&lt;';
50 public $last_link = 'Last &rsaquo;';
51 public $uri_segment = 3;
52 public $full_tag_open = '';
53 public $full_tag_close = '';
54 public $first_tag_open = '';
55 public $first_tag_close = '&nbsp;';
56 public $last_tag_open = '&nbsp;';
57 public $last_tag_close = '';
58 public $first_url = ''; // Alternative URL for the First Page.
59 public $cur_tag_open = '&nbsp;<strong>';
60 public $cur_tag_close = '</strong>';
61 public $next_tag_open = '&nbsp;';
62 public $next_tag_close = '&nbsp;';
63 public $prev_tag_open = '&nbsp;';
64 public $prev_tag_close = '';
65 public $num_tag_open = '&nbsp;';
66 public $num_tag_close = '';
67 public $page_query_string = FALSE;
68 public $query_string_segment = 'per_page';
69 public $display_pages = TRUE;
70 public $anchor_class = '';
Andrey Andreev5a1e5e32012-06-12 11:28:26 +030071 public $attr_rel = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +000072
73 /**
74 * Constructor
75 *
Derek Allard2067d1a2008-11-13 22:59:24 +000076 * @param array initialization parameters
Andrey Andreev56454792012-05-17 14:32:19 +030077 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +000078 */
Greg Akera9263282010-11-10 15:26:43 -060079 public function __construct($params = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000080 {
Eric Barnesbce41402011-12-03 23:47:41 -050081 $this->initialize($params);
Andrey Andreev796bc952012-03-26 19:40:40 +030082 log_message('debug', 'Pagination Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +000083 }
Derek Allardfaac15e2009-03-07 17:17:58 +000084
Derek Allard2067d1a2008-11-13 22:59:24 +000085 // --------------------------------------------------------------------
Derek Allardfaac15e2009-03-07 17:17:58 +000086
Derek Allard2067d1a2008-11-13 22:59:24 +000087 /**
88 * Initialize Preferences
89 *
Derek Allard2067d1a2008-11-13 22:59:24 +000090 * @param array initialization parameters
91 * @return void
92 */
Eric Barnes9a4902a2011-12-03 23:46:06 -050093 public function initialize($params = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000094 {
95 if (count($params) > 0)
96 {
97 foreach ($params as $key => $val)
98 {
Andrey Andreev1a3885b2012-05-02 10:23:12 +030099 if ($key === 'anchor_class')
100 {
Andrey Andreev7eb7ebf2012-06-12 10:26:27 +0300101 $this->anchor_class = ($val) ? 'class="'.$val.'" ' : '';
Andrey Andreev1a3885b2012-05-02 10:23:12 +0300102 }
103 elseif (isset($this->$key))
Derek Allard2067d1a2008-11-13 22:59:24 +0000104 {
105 $this->$key = $val;
106 }
107 }
108 }
109 }
Derek Allardfaac15e2009-03-07 17:17:58 +0000110
Derek Allard2067d1a2008-11-13 22:59:24 +0000111 // --------------------------------------------------------------------
Derek Allardfaac15e2009-03-07 17:17:58 +0000112
Derek Allard2067d1a2008-11-13 22:59:24 +0000113 /**
114 * Generate the pagination links
115 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000116 * @return string
Derek Allardfaac15e2009-03-07 17:17:58 +0000117 */
Eric Barnes9a4902a2011-12-03 23:46:06 -0500118 public function create_links()
Derek Allard2067d1a2008-11-13 22:59:24 +0000119 {
120 // If our item count or per-page total is zero there is no need to continue.
Alex Bilbied261b1e2012-06-02 11:12:16 +0100121 if ($this->total_rows === 0 OR $this->per_page === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000122 {
Derek Allardfaac15e2009-03-07 17:17:58 +0000123 return '';
Derek Allard2067d1a2008-11-13 22:59:24 +0000124 }
125
126 // Calculate the total number of pages
Ronald Beilsmacfb70212011-12-29 09:57:49 +0100127 $num_pages = (int) ceil($this->total_rows / $this->per_page);
Derek Allard2067d1a2008-11-13 22:59:24 +0000128
129 // Is there only one page? Hm... nothing more to do here then.
Ronald Beilsmacfb70212011-12-29 09:57:49 +0100130 if ($num_pages === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +0000131 {
132 return '';
133 }
134
Aaron Kuzemchak11c5f162011-09-03 20:59:07 -0400135 // Set the base page index for starting page number
Aaron Kuzemchaka5e13f92011-09-04 16:39:47 -0400136 $base_page = ($this->use_page_numbers) ? 1 : 0;
Aaron Kuzemchak11c5f162011-09-03 20:59:07 -0400137
Derek Allardfaac15e2009-03-07 17:17:58 +0000138 // Determine the current page number.
Derek Allard2067d1a2008-11-13 22:59:24 +0000139 $CI =& get_instance();
Derek Allardfaac15e2009-03-07 17:17:58 +0000140
Eric Barnes3b376592012-01-04 00:28:27 -0500141 // See if we are using a prefix or suffix on links
Alex Bilbied261b1e2012-06-02 11:12:16 +0100142 if ($this->prefix !== '' OR $this->suffix !== '')
Eric Barnes8d727f12012-01-04 00:06:36 -0500143 {
Eric Barnes3b376592012-01-04 00:28:27 -0500144 $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->segment($this->uri_segment));
Eric Barnes8d727f12012-01-04 00:06:36 -0500145 }
146
Derek Allard2067d1a2008-11-13 22:59:24 +0000147 if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
148 {
Andrey Andreev7eb7ebf2012-06-12 10:26:27 +0300149 if ($CI->input->get($this->query_string_segment) != $base_page)
Derek Allard2067d1a2008-11-13 22:59:24 +0000150 {
Andrey Andreev33987e62011-12-24 19:48:45 +0200151 $this->cur_page = (int) $CI->input->get($this->query_string_segment);
Derek Allard2067d1a2008-11-13 22:59:24 +0000152 }
153 }
Alex Bilbied261b1e2012-06-02 11:12:16 +0100154 elseif ( ! $this->cur_page && $CI->uri->segment($this->uri_segment) !== $base_page)
Derek Allard2067d1a2008-11-13 22:59:24 +0000155 {
Andrey Andreev33987e62011-12-24 19:48:45 +0200156 $this->cur_page = (int) $CI->uri->segment($this->uri_segment);
Derek Allard2067d1a2008-11-13 22:59:24 +0000157 }
Eric Barnes9a4902a2011-12-03 23:46:06 -0500158
Andrey Andreev33987e62011-12-24 19:48:45 +0200159 // Set current page to 1 if it's not valid or if using page numbers instead of offset
Alex Bilbied261b1e2012-06-02 11:12:16 +0100160 if ( ! is_numeric($this->cur_page) OR ($this->use_page_numbers && $this->cur_page === 0))
Aaron Kuzemchak11c5f162011-09-03 20:59:07 -0400161 {
162 $this->cur_page = $base_page;
163 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000164
Eric Barnes3b376592012-01-04 00:28:27 -0500165 $this->num_links = (int) $this->num_links;
Derek Allardfaac15e2009-03-07 17:17:58 +0000166
Derek Allard2067d1a2008-11-13 22:59:24 +0000167 if ($this->num_links < 1)
168 {
169 show_error('Your number of links must be a positive number.');
170 }
Derek Allardfaac15e2009-03-07 17:17:58 +0000171
Derek Allard2067d1a2008-11-13 22:59:24 +0000172 // Is the page number beyond the result range?
173 // If so we show the last page
Aaron Kuzemchak11c5f162011-09-03 20:59:07 -0400174 if ($this->use_page_numbers)
Derek Allard2067d1a2008-11-13 22:59:24 +0000175 {
Aaron Kuzemchak11c5f162011-09-03 20:59:07 -0400176 if ($this->cur_page > $num_pages)
177 {
178 $this->cur_page = $num_pages;
179 }
180 }
Andrey Andreev796bc952012-03-26 19:40:40 +0300181 elseif ($this->cur_page > $this->total_rows)
Aaron Kuzemchak11c5f162011-09-03 20:59:07 -0400182 {
Andrey Andreev796bc952012-03-26 19:40:40 +0300183 $this->cur_page = ($num_pages - 1) * $this->per_page;
Derek Allard2067d1a2008-11-13 22:59:24 +0000184 }
Derek Allardfaac15e2009-03-07 17:17:58 +0000185
Derek Allard2067d1a2008-11-13 22:59:24 +0000186 $uri_page_number = $this->cur_page;
Eric Barnes9a4902a2011-12-03 23:46:06 -0500187
Aaron Kuzemchak11c5f162011-09-03 20:59:07 -0400188 if ( ! $this->use_page_numbers)
189 {
190 $this->cur_page = floor(($this->cur_page/$this->per_page) + 1);
191 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000192
193 // Calculate the start and end numbers. These determine
194 // which number to start and end the digit links with
Andrey Andreev796bc952012-03-26 19:40:40 +0300195 $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;
196 $end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;
Derek Allard2067d1a2008-11-13 22:59:24 +0000197
Andrey Andreev796bc952012-03-26 19:40:40 +0300198 // Is pagination being used over GET or POST? If get, add a per_page query
Derek Allard2067d1a2008-11-13 22:59:24 +0000199 // string. If post, add a trailing slash to the base URL if needed
200 if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
201 {
202 $this->base_url = rtrim($this->base_url).'&amp;'.$this->query_string_segment.'=';
203 }
204 else
205 {
206 $this->base_url = rtrim($this->base_url, '/') .'/';
207 }
208
Barry Mienydd671972010-10-04 16:33:58 +0200209 // And here we go...
Derek Allard2067d1a2008-11-13 22:59:24 +0000210 $output = '';
211
212 // Render the "First" link
Andrey Andreev796bc952012-03-26 19:40:40 +0300213 if ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1))
Derek Allard2067d1a2008-11-13 22:59:24 +0000214 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100215 $first_url = ($this->first_url === '') ? $this->base_url : $this->first_url;
Andrey Andreev5a1e5e32012-06-12 11:28:26 +0300216 $output .= $this->first_tag_open.'<a '.$this->anchor_class.'href="'.$first_url.'"'.$this->_attr_rel('start').'>'
217 .$this->first_link.'</a>'.$this->first_tag_close;
Derek Allard2067d1a2008-11-13 22:59:24 +0000218 }
219
220 // Render the "previous" link
Alex Bilbied261b1e2012-06-02 11:12:16 +0100221 if ($this->prev_link !== FALSE && $this->cur_page !== 1)
Derek Allard2067d1a2008-11-13 22:59:24 +0000222 {
Aaron Kuzemchaka5e13f92011-09-04 16:39:47 -0400223 $i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;
Barry Mienydd671972010-10-04 16:33:58 +0200224
Alex Bilbied261b1e2012-06-02 11:12:16 +0100225 if ($i === $base_page && $this->first_url !== '')
Robin Sowell2a6c1da2010-05-24 12:20:03 -0400226 {
Andrey Andreev5a1e5e32012-06-12 11:28:26 +0300227 $output .= $this->prev_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'"'.$this->_attr_rel('prev').'>'
228 .$this->prev_link.'</a>'.$this->prev_tag_close;
Robin Sowell2a6c1da2010-05-24 12:20:03 -0400229 }
230 else
231 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100232 $i = ($i === $base_page) ? '' : $this->prefix.$i.$this->suffix;
Andrey Andreev5a1e5e32012-06-12 11:28:26 +0300233 $output .= $this->prev_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$i.'"'.$this->_attr_rel('prev').'>'
234 .$this->prev_link.'</a>'.$this->prev_tag_close;
Robin Sowell2a6c1da2010-05-24 12:20:03 -0400235 }
Barry Mienydd671972010-10-04 16:33:58 +0200236
Derek Allard2067d1a2008-11-13 22:59:24 +0000237 }
238
Derek Allarde01fd0f2010-07-05 11:06:07 -0400239 // Render the pages
240 if ($this->display_pages !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000241 {
Derek Allarde01fd0f2010-07-05 11:06:07 -0400242 // Write the digit links
243 for ($loop = $start -1; $loop <= $end; $loop++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000244 {
Aaron Kuzemchaka5e13f92011-09-04 16:39:47 -0400245 $i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;
Derek Allarde01fd0f2010-07-05 11:06:07 -0400246
Aaron Kuzemchak11c5f162011-09-03 20:59:07 -0400247 if ($i >= $base_page)
Derek Allard2067d1a2008-11-13 22:59:24 +0000248 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100249 if ($this->cur_page === $loop)
Robin Sowell2a6c1da2010-05-24 12:20:03 -0400250 {
Derek Allarde01fd0f2010-07-05 11:06:07 -0400251 $output .= $this->cur_tag_open.$loop.$this->cur_tag_close; // Current page
Robin Sowell2a6c1da2010-05-24 12:20:03 -0400252 }
253 else
254 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100255 $n = ($i === $base_page) ? '' : $i;
Barry Mienydd671972010-10-04 16:33:58 +0200256
Alex Bilbied261b1e2012-06-02 11:12:16 +0100257 if ($n === '' && $this->first_url !== '')
Derek Allarde01fd0f2010-07-05 11:06:07 -0400258 {
Andrey Andreev5a1e5e32012-06-12 11:28:26 +0300259 $output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->first_url.'"'.$this->_attr_rel('start').'>'
260 .$loop.'</a>'.$this->num_tag_close;
Derek Allarde01fd0f2010-07-05 11:06:07 -0400261 }
262 else
263 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100264 $n = ($n === '') ? '' : $this->prefix.$n.$this->suffix;
Barry Mienydd671972010-10-04 16:33:58 +0200265
Andrey Andreev5a1e5e32012-06-12 11:28:26 +0300266 $output .= $this->num_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$n.'"'.$this->_attr_rel().'>'
267 .$loop.'</a>'.$this->num_tag_close;
Derek Allarde01fd0f2010-07-05 11:06:07 -0400268 }
Robin Sowell2a6c1da2010-05-24 12:20:03 -0400269 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000270 }
271 }
272 }
273
274 // Render the "next" link
Andrey Andreev796bc952012-03-26 19:40:40 +0300275 if ($this->next_link !== FALSE && $this->cur_page < $num_pages)
Derek Allard2067d1a2008-11-13 22:59:24 +0000276 {
Aaron Kuzemchaka5e13f92011-09-04 16:39:47 -0400277 $i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;
Aaron Kuzemchak11c5f162011-09-03 20:59:07 -0400278
Andrey Andreev5a1e5e32012-06-12 11:28:26 +0300279 $output .= $this->next_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$this->_attr_rel('next').'>'
280 .$this->next_link.'</a>'.$this->next_tag_close;
Derek Allard2067d1a2008-11-13 22:59:24 +0000281 }
282
283 // Render the "Last" link
Andrey Andreev796bc952012-03-26 19:40:40 +0300284 if ($this->last_link !== FALSE && ($this->cur_page + $this->num_links) < $num_pages)
Derek Allard2067d1a2008-11-13 22:59:24 +0000285 {
Aaron Kuzemchaka5e13f92011-09-04 16:39:47 -0400286 $i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;
Phil Sturgeonc00a5a02011-11-22 15:25:32 +0000287
Andrey Andreev5a1e5e32012-06-12 11:28:26 +0300288 $output .= $this->last_tag_open.'<a '.$this->anchor_class.'href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$this->_attr_rel().'>'
289 .$this->last_link.'</a>'.$this->last_tag_close;
Derek Allard2067d1a2008-11-13 22:59:24 +0000290 }
291
Phil Sturgeonc00a5a02011-11-22 15:25:32 +0000292 // Kill double slashes. Note: Sometimes we can end up with a double slash
Derek Allard2067d1a2008-11-13 22:59:24 +0000293 // in the penultimate link so we'll kill all double slashes.
Andrey Andreev796bc952012-03-26 19:40:40 +0300294 $output = preg_replace('#([^:])//+#', '\\1/', $output);
Derek Allard2067d1a2008-11-13 22:59:24 +0000295
296 // Add the wrapper HTML if exists
Andrey Andreev796bc952012-03-26 19:40:40 +0300297 return $this->full_tag_open.$output.$this->full_tag_close;
Derek Allard2067d1a2008-11-13 22:59:24 +0000298 }
Andrey Andreev796bc952012-03-26 19:40:40 +0300299
Andrey Andreev5a1e5e32012-06-12 11:28:26 +0300300 // --------------------------------------------------------------------
301
302 /**
303 * Add "rel" attribute
304 *
305 * @param string
306 * @return string
307 */
308 protected function _attr_rel($value = '')
309 {
310 if (empty($this->attr_rel) OR ($this->attr_rel === TRUE && empty($value)))
311 {
312 return '';
313 }
314 elseif ( ! is_bool($this->attr_rel))
315 {
316 $value = $this->attr_rel;
317 }
318
319 return ' rel="'.$value.'"';
320 }
321
Derek Allard2067d1a2008-11-13 22:59:24 +0000322}
Derek Allard2067d1a2008-11-13 22:59:24 +0000323
324/* End of file Pagination.php */
Andrey Andreev796bc952012-03-26 19:40:40 +0300325/* Location: ./system/libraries/Pagination.php */