PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/system/codeigniter/libraries/Pagination.php

https://github.com/asalem/pyrocms
PHP | 654 lines | 256 code | 94 blank | 304 comment | 38 complexity | d494d038f9fed2fdb8a1f7c75450a486 MD5 | raw file
Possible License(s): CC-BY-3.0, BSD-3-Clause, CC0-1.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, MIT
  1. <?php
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 5.2.4 or newer
  6. *
  7. * NOTICE OF LICENSE
  8. *
  9. * Licensed under the Open Software License version 3.0
  10. *
  11. * 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. *
  19. * @package CodeIgniter
  20. * @author EllisLab Dev Team
  21. * @copyright Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
  22. * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
  23. * @link http://codeigniter.com
  24. * @since Version 1.0
  25. * @filesource
  26. */
  27. defined('BASEPATH') OR exit('No direct script access allowed');
  28. /**
  29. * Pagination Class
  30. *
  31. * @package CodeIgniter
  32. * @subpackage Libraries
  33. * @category Pagination
  34. * @author EllisLab Dev Team
  35. * @link http://codeigniter.com/user_guide/libraries/pagination.html
  36. */
  37. class CI_Pagination {
  38. /**
  39. * Base URL
  40. *
  41. * The page that we're linking to
  42. *
  43. * @var string
  44. */
  45. protected $base_url = '';
  46. /**
  47. * Prefix
  48. *
  49. * @var string
  50. */
  51. protected $prefix = '';
  52. /**
  53. * Suffix
  54. *
  55. * @var string
  56. */
  57. protected $suffix = '';
  58. /**
  59. * Total number of items
  60. *
  61. * @var int
  62. */
  63. protected $total_rows = 0;
  64. /**
  65. * Items per page
  66. *
  67. * @var int
  68. */
  69. protected $per_page = 10;
  70. /**
  71. * Number of links to show
  72. *
  73. * Relates to "digit" type links shown before/after
  74. * the currently viewed page.
  75. *
  76. * @var int
  77. */
  78. protected $num_links = 2;
  79. /**
  80. * Current page
  81. *
  82. * @var int
  83. */
  84. protected $cur_page = 0;
  85. /**
  86. * Use page numbers flag
  87. *
  88. * Whether to use actual page numbers instead of an offset
  89. *
  90. * @var bool
  91. */
  92. protected $use_page_numbers = FALSE;
  93. /**
  94. * First link
  95. *
  96. * @var string
  97. */
  98. protected $first_link = '&lsaquo; First';
  99. /**
  100. * Next link
  101. *
  102. * @var string
  103. */
  104. protected $next_link = '&gt;';
  105. /**
  106. * Previous link
  107. *
  108. * @var string
  109. */
  110. protected $prev_link = '&lt;';
  111. /**
  112. * Last link
  113. *
  114. * @var string
  115. */
  116. protected $last_link = 'Last &rsaquo;';
  117. /**
  118. * URI Segment
  119. *
  120. * @var int
  121. */
  122. protected $uri_segment = 0;
  123. /**
  124. * Full tag open
  125. *
  126. * @var string
  127. */
  128. protected $full_tag_open = '';
  129. /**
  130. * Full tag close
  131. *
  132. * @var string
  133. */
  134. protected $full_tag_close = '';
  135. /**
  136. * First tag open
  137. *
  138. * @var string
  139. */
  140. protected $first_tag_open = '';
  141. /**
  142. * First tag close
  143. *
  144. * @var string
  145. */
  146. protected $first_tag_close = '';
  147. /**
  148. * Last tag open
  149. *
  150. * @var string
  151. */
  152. protected $last_tag_open = '';
  153. /**
  154. * Last tag close
  155. *
  156. * @var string
  157. */
  158. protected $last_tag_close = '';
  159. /**
  160. * First URL
  161. *
  162. * An alternative URL for the first page
  163. *
  164. * @var string
  165. */
  166. protected $first_url = '';
  167. /**
  168. * Current tag open
  169. *
  170. * @var string
  171. */
  172. protected $cur_tag_open = '<strong>';
  173. /**
  174. * Current tag close
  175. *
  176. * @var string
  177. */
  178. protected $cur_tag_close = '</strong>';
  179. /**
  180. * Next tag open
  181. *
  182. * @var string
  183. */
  184. protected $next_tag_open = '';
  185. /**
  186. * Next tag close
  187. *
  188. * @var string
  189. */
  190. protected $next_tag_close = '';
  191. /**
  192. * Previous tag open
  193. *
  194. * @var string
  195. */
  196. protected $prev_tag_open = '';
  197. /**
  198. * Previous tag close
  199. *
  200. * @var string
  201. */
  202. protected $prev_tag_close = '';
  203. /**
  204. * Number tag open
  205. *
  206. * @var string
  207. */
  208. protected $num_tag_open = '';
  209. /**
  210. * Number tag close
  211. *
  212. * @var string
  213. */
  214. protected $num_tag_close = '';
  215. /**
  216. * Page query string flag
  217. *
  218. * @var bool
  219. */
  220. protected $page_query_string = TRUE;
  221. /**
  222. * Query string segment
  223. *
  224. * @var string
  225. */
  226. protected $query_string_segment = 'page';
  227. /**
  228. * Display pages flag
  229. *
  230. * @var bool
  231. */
  232. protected $display_pages = TRUE;
  233. /**
  234. * Attributes
  235. *
  236. * @var string
  237. */
  238. protected $_attributes = '';
  239. /**
  240. * Link types
  241. *
  242. * "rel" attribute
  243. *
  244. * @see CI_Pagination::_attr_rel()
  245. * @var array
  246. */
  247. protected $_link_types = array();
  248. /**
  249. * Reuse query string flag
  250. *
  251. * @var bool
  252. */
  253. protected $reuse_query_string = FALSE;
  254. /**
  255. * Data page attribute
  256. *
  257. * @var string
  258. */
  259. protected $data_page_attr = 'data-ci-pagination-page';
  260. // --------------------------------------------------------------------
  261. /**
  262. * Constructor
  263. *
  264. * @param array $params Initialization parameters
  265. * @return void
  266. */
  267. public function __construct($params = array())
  268. {
  269. $this->initialize($params);
  270. log_message('debug', 'Pagination Class Initialized');
  271. }
  272. // --------------------------------------------------------------------
  273. /**
  274. * Initialize Preferences
  275. *
  276. * @param array $params Initialization parameters
  277. * @return void
  278. */
  279. public function initialize($params = array())
  280. {
  281. if (isset($params['attributes']) && is_array($params['attributes']))
  282. {
  283. $this->_parse_attributes($params['attributes']);
  284. unset($params['attributes']);
  285. }
  286. // Deprecated legacy support for the anchor_class option
  287. // Should be removed in CI 3.1+
  288. if (isset($params['anchor_class']))
  289. {
  290. empty($params['anchor_class']) OR $attributes['class'] = $params['anchor_class'];
  291. unset($params['anchor_class']);
  292. }
  293. if (count($params) > 0)
  294. {
  295. foreach ($params as $key => $val)
  296. {
  297. if (isset($this->$key))
  298. {
  299. $this->$key = $val;
  300. }
  301. }
  302. }
  303. }
  304. // --------------------------------------------------------------------
  305. /**
  306. * Generate the pagination links
  307. *
  308. * @return string
  309. */
  310. public function create_links()
  311. {
  312. // If our item count or per-page total is zero there is no need to continue.
  313. if ($this->total_rows === 0 OR $this->per_page === 0)
  314. {
  315. return '';
  316. }
  317. // Calculate the total number of pages
  318. $num_pages = (int) ceil($this->total_rows / $this->per_page);
  319. // Is there only one page? Hm... nothing more to do here then.
  320. if ($num_pages === 1)
  321. {
  322. return '';
  323. }
  324. // Check the user defined number of links.
  325. $this->num_links = (int) $this->num_links;
  326. if ($this->num_links < 1)
  327. {
  328. show_error('Your number of links must be a positive number.');
  329. }
  330. $CI =& get_instance();
  331. // Keep any existing query string items.
  332. // Note: Has nothing to do with any other query string option.
  333. if ($this->reuse_query_string === TRUE)
  334. {
  335. $get = $CI->input->get();
  336. // Unset the controll, method, old-school routing options
  337. unset($get['c'], $get['m'], $get[$this->query_string_segment]);
  338. }
  339. else
  340. {
  341. $get = array();
  342. }
  343. // Put together our base and first URLs.
  344. $this->base_url = trim($this->base_url);
  345. $query_string = '';
  346. $query_string_sep = (strpos($this->base_url, '?') === FALSE) ? '?' : '&amp;';
  347. // Are we using query strings?
  348. if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
  349. {
  350. // If a custom first_url hasn't been specified, we'll create one from
  351. // the base_url, but without the page item.
  352. if ($this->first_url === '')
  353. {
  354. $this->first_url = $this->base_url;
  355. // If we saved any GET items earlier, make sure they're appended.
  356. if ( ! empty($get))
  357. {
  358. $this->first_url .= $query_string_sep.http_build_query($get);
  359. }
  360. }
  361. // Add the page segment to the end of the query string, where the
  362. // page number will be appended.
  363. $this->base_url .= $query_string_sep.http_build_query(array_merge($get, array($this->query_string_segment => '')));
  364. }
  365. else
  366. {
  367. // Standard segment mode.
  368. // Generate our saved query string to append later after the page number.
  369. if ( ! empty($get))
  370. {
  371. $query_string = $query_string_sep.http_build_query($get);
  372. $this->suffix .= $query_string;
  373. }
  374. // Does the base_url have the query string in it?
  375. // If we're supposed to save it, remove it so we can append it later.
  376. if ($this->reuse_query_string === TRUE && ($base_query_pos = strpos($this->base_url, '?')) !== FALSE)
  377. {
  378. $this->base_url = substr($this->base_url, 0, $base_query_pos);
  379. }
  380. if ($this->first_url === '')
  381. {
  382. $this->first_url = $this->base_url.$query_string;
  383. }
  384. $this->base_url = rtrim($this->base_url, '/').'/';
  385. }
  386. // Determine the current page number.
  387. $base_page = ($this->use_page_numbers) ? 1 : 0;
  388. // Are we using query strings?
  389. if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
  390. {
  391. $this->cur_page = $CI->input->get($this->query_string_segment);
  392. }
  393. else
  394. {
  395. // Default to the last segment number if one hasn't been defined.
  396. if ($this->uri_segment === 0)
  397. {
  398. $this->uri_segment = count($CI->uri->segment_array());
  399. }
  400. $this->cur_page = $CI->uri->segment($this->uri_segment);
  401. // Remove any specified prefix/suffix from the segment.
  402. if ($this->prefix !== '' OR $this->suffix !== '')
  403. {
  404. $this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page);
  405. }
  406. }
  407. // If something isn't quite right, back to the default base page.
  408. if ( ! ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int) $this->cur_page === 0))
  409. {
  410. $this->cur_page = $base_page;
  411. }
  412. else
  413. {
  414. // Make sure we're using integers for comparisons later.
  415. $this->cur_page = (int) $this->cur_page;
  416. }
  417. // Is the page number beyond the result range?
  418. // If so, we show the last page.
  419. if ($this->use_page_numbers)
  420. {
  421. if ($this->cur_page > $num_pages)
  422. {
  423. $this->cur_page = $num_pages;
  424. }
  425. }
  426. elseif ($this->cur_page > $this->total_rows)
  427. {
  428. $this->cur_page = ($num_pages - 1) * $this->per_page;
  429. }
  430. $uri_page_number = $this->cur_page;
  431. // If we're using offset instead of page numbers, convert it
  432. // to a page number, so we can generate the surrounding number links.
  433. if ( ! $this->use_page_numbers)
  434. {
  435. $this->cur_page = (int) floor(($this->cur_page/$this->per_page) + 1);
  436. }
  437. // Calculate the start and end numbers. These determine
  438. // which number to start and end the digit links with.
  439. $start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;
  440. $end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;
  441. // And here we go...
  442. $output = '';
  443. // Render the "First" link.
  444. if ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1))
  445. {
  446. // Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.
  447. $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);
  448. $output .= $this->first_tag_open.'<a href="'.$this->first_url.'"'.$attributes.$this->_attr_rel('start').'>'
  449. .$this->first_link.'</a>'.$this->first_tag_close;
  450. }
  451. // Render the "Previous" link.
  452. if ($this->prev_link !== FALSE && $this->cur_page !== 1)
  453. {
  454. $i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;
  455. $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
  456. if ($i === $base_page)
  457. {
  458. // First page
  459. $output .= $this->prev_tag_open.'<a href="'.$this->first_url.'"'.$attributes.$this->_attr_rel('prev').'>'
  460. .$this->prev_link.'</a>'.$this->prev_tag_close;
  461. }
  462. else
  463. {
  464. $append = $this->prefix.$i.$this->suffix;
  465. $output .= $this->prev_tag_open.'<a href="'.$this->base_url.$append.'"'.$attributes.$this->_attr_rel('prev').'>'
  466. .$this->prev_link.'</a>'.$this->prev_tag_close;
  467. }
  468. }
  469. // Render the pages
  470. if ($this->display_pages !== FALSE)
  471. {
  472. // Write the digit links
  473. for ($loop = $start -1; $loop <= $end; $loop++)
  474. {
  475. $i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;
  476. $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
  477. if ($i >= $base_page)
  478. {
  479. if ($this->cur_page === $loop)
  480. {
  481. // Current page
  482. $output .= $this->cur_tag_open.$loop.$this->cur_tag_close;
  483. }
  484. elseif ($i === $base_page)
  485. {
  486. // First page
  487. $output .= $this->num_tag_open.'<a href="'.$this->first_url.'"'.$attributes.$this->_attr_rel('start').'>'
  488. .$loop.'</a>'.$this->num_tag_close;
  489. }
  490. else
  491. {
  492. $append = $this->prefix.$i.$this->suffix;
  493. $output .= $this->num_tag_open.'<a href="'.$this->base_url.$append.'"'.$attributes.$this->_attr_rel('start').'>'
  494. .$loop.'</a>'.$this->num_tag_close;
  495. }
  496. }
  497. }
  498. }
  499. // Render the "next" link
  500. if ($this->next_link !== FALSE && $this->cur_page < $num_pages)
  501. {
  502. $i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;
  503. $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
  504. $output .= $this->next_tag_open.'<a href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$attributes
  505. .$this->_attr_rel('next').'>'.$this->next_link.'</a>'.$this->next_tag_close;
  506. }
  507. // Render the "Last" link
  508. if ($this->last_link !== FALSE && ($this->cur_page + $this->num_links) < $num_pages)
  509. {
  510. $i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;
  511. $attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
  512. $output .= $this->last_tag_open.'<a href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$attributes.'>'
  513. .$this->last_link.'</a>'.$this->last_tag_close;
  514. }
  515. // Kill double slashes. Note: Sometimes we can end up with a double slash
  516. // in the penultimate link so we'll kill all double slashes.
  517. $output = preg_replace('#([^:])//+#', '\\1/', $output);
  518. // Add the wrapper HTML if exists
  519. return $this->full_tag_open.$output.$this->full_tag_close;
  520. }
  521. // --------------------------------------------------------------------
  522. /**
  523. * Parse attributes
  524. *
  525. * @param array $attributes
  526. * @return void
  527. */
  528. protected function _parse_attributes($attributes)
  529. {
  530. isset($attributes['rel']) OR $attributes['rel'] = TRUE;
  531. $this->_link_types = ($attributes['rel'])
  532. ? array('start' => 'start', 'prev' => 'prev', 'next' => 'next')
  533. : array();
  534. unset($attributes['rel']);
  535. $this->_attributes = '';
  536. foreach ($attributes as $key => $value)
  537. {
  538. $this->_attributes .= ' '.$key.'="'.$value.'"';
  539. }
  540. }
  541. // --------------------------------------------------------------------
  542. /**
  543. * Add "rel" attribute
  544. *
  545. * @link http://www.w3.org/TR/html5/links.html#linkTypes
  546. * @param string $type
  547. * @return string
  548. */
  549. protected function _attr_rel($type)
  550. {
  551. if (isset($this->_link_types[$type]))
  552. {
  553. unset($this->_link_types[$type]);
  554. return ' rel="'.$type.'"';
  555. }
  556. return '';
  557. }
  558. }
  559. /* End of file Pagination.php */
  560. /* Location: ./system/libraries/Pagination.php */