PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/core/classes/pagination.php

https://bitbucket.org/sriedel/iccrm-wip
PHP | 390 lines | 242 code | 52 blank | 96 comment | 26 complexity | 1a0aa97136664850145809ccbba4c2e5 MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /**
  3. * Part of the Fuel framework.
  4. *
  5. * @package Fuel
  6. * @version 1.0
  7. * @license MIT License
  8. * @copyright 2010 - 2012 Fuel Development Team
  9. */
  10. namespace Fuel\Core;
  11. class Pagination
  12. {
  13. /**
  14. * @var array Pagination instances
  15. */
  16. protected static $_instances = array();
  17. /**
  18. * @var array Pagination default instance
  19. */
  20. protected static $_instance = null;
  21. /**
  22. * Init
  23. *
  24. * Loads in the config and sets the variables
  25. *
  26. * @return void
  27. */
  28. public static function _init()
  29. {
  30. \Config::load('pagination', true);
  31. \Lang::load('pagination', true);
  32. }
  33. /**
  34. * Static access to the default instance
  35. *
  36. * @return mixed
  37. * @throws BadMethodCallException if the request method does not exist
  38. */
  39. public static function __callStatic($name, $arguments)
  40. {
  41. // old pre-1.4 mapping to new instance methods
  42. static $mapping = array(
  43. 'get' => '__get',
  44. 'set' => '__set',
  45. 'set_config' => '__set',
  46. 'create_links' => 'render',
  47. 'page_links' => 'pages_render',
  48. 'prev_link' => 'previous',
  49. 'next_link' => 'next',
  50. );
  51. array_key_exists($name, $mapping) and $name = $mapping[$name];
  52. // call the method on the default instance
  53. if ($instance = static::instance() and method_exists($instance, $name))
  54. {
  55. return call_user_func_array(array($instance, $name), $arguments);
  56. }
  57. throw new \BadMethodCallException('The pagination class doesn\'t have a method called "'.$name.'"');
  58. }
  59. /**
  60. * forge a new pagination instance
  61. *
  62. * @return \Pagination a new pagination instance
  63. */
  64. public static function forge($name = 'default', $config = array())
  65. {
  66. if ($exists = static::instance($name))
  67. {
  68. \Error::notice('Pagination with this name exists already, cannot be overwritten.');
  69. return $exists;
  70. }
  71. static::$_instances[$name] = new static($config);
  72. if ($name == 'default')
  73. {
  74. static::$_instance = static::$_instances[$name];
  75. }
  76. return static::$_instances[$name];
  77. }
  78. /**
  79. * retrieve an existing pagination instance
  80. *
  81. * @return \Pagination a existing pagination instance
  82. */
  83. public static function instance($name = null)
  84. {
  85. if ($name !== null)
  86. {
  87. if ( ! array_key_exists($name, static::$_instances))
  88. {
  89. return false;
  90. }
  91. return static::$_instances[$name];
  92. }
  93. if (static::$_instance === null)
  94. {
  95. static::$_instance = static::forge();
  96. }
  97. return static::$_instance;
  98. }
  99. // --------------------------------------------------------------------
  100. /**
  101. * instance configuration values
  102. */
  103. protected $config = array(
  104. 'current_page' => null,
  105. 'offset' => 0,
  106. 'per_page' => 10,
  107. 'total_pages' => 0,
  108. 'total_items' => 0,
  109. 'num_links' => 5,
  110. 'uri_segment' => 3,
  111. 'pagination_url' => null,
  112. );
  113. /**
  114. * instance template values
  115. */
  116. protected $template = array(
  117. 'wrapper' => "<div class=\"pagination\">\n\t{pagination}\n</div>\n",
  118. 'previous' => "<span class=\"previous\">\n\t{link}\n</span>\n",
  119. 'previous-link' => "\t\t<a href=\"{uri}\">{page}</a>\n",
  120. 'previous-inactive' => "<span class=\"previous-inactive\">\n\t{link}\n</span>\n",
  121. 'previous-inactive-link' => "\t\t<a href=\"{uri}\">{page}</a>\n",
  122. 'regular' => "<span>\n\t{link}\n</span>\n",
  123. 'regular-link' => "\t\t<a href=\"{uri}\">{page}</a>\n",
  124. 'active' => "<span class=\"active\">\n\t{link}\n</span>\n",
  125. 'active-link' => "\t\t<a href=\"{uri}\">{page}</a>\n",
  126. 'next' => "<span class=\"next\">\n\t{link}\n</span>\n",
  127. 'next-link' => "\t\t<a href=\"{uri}\">{page}</a>\n",
  128. 'next-inactive' => "<span class=\"next-inactive\">\n\t{link}\n</span>\n",
  129. 'next-inactive-link' => "\t\t<a href=\"{uri}\">{page}</a>\n",
  130. );
  131. /**
  132. *
  133. */
  134. public function __construct($config = array())
  135. {
  136. // make sure config is an array
  137. is_array($config) or $config = array('name' => $config);
  138. // and we have a template name
  139. array_key_exists('name', $config) or $config['name'] = \Config::get('pagination.active', 'default');
  140. // merge the config passed with the defined configuration
  141. $config = array_merge(\Config::get('pagination.'.$config['name'], array()), $config);
  142. // don't need the template name anymore
  143. unset($config['name']);
  144. // update the instance default config with the data passed
  145. foreach ($config as $key => $value)
  146. {
  147. $this->__set($key, $value);
  148. }
  149. }
  150. /**
  151. * configuration value getter
  152. */
  153. public function __get($name)
  154. {
  155. if (array_key_exists($name, $this->config))
  156. {
  157. return $this->config[$name];
  158. }
  159. elseif (array_key_exists($name, $this->template))
  160. {
  161. return $this->template[$name];
  162. }
  163. else
  164. {
  165. return null;
  166. }
  167. }
  168. /**
  169. * configuration value setter
  170. */
  171. public function __set($name, $value = null)
  172. {
  173. if (is_array($name))
  174. {
  175. foreach($name as $key => $value)
  176. {
  177. $this->__set($key, $value);
  178. }
  179. }
  180. else
  181. {
  182. if (array_key_exists($name, $this->config))
  183. {
  184. $this->config[$name] = $value;
  185. }
  186. elseif (array_key_exists($name, $this->template))
  187. {
  188. $this->template[$name] = $value;
  189. }
  190. }
  191. // update the page counters
  192. $this->_recalculate();
  193. }
  194. /**
  195. * Creates the pagination markup
  196. *
  197. * @return string Markup for the pagination block
  198. */
  199. public function render()
  200. {
  201. // no links if we only have one page
  202. if ($this->config['total_pages'] == 1)
  203. {
  204. return '';
  205. }
  206. $html = str_replace(
  207. '{pagination}',
  208. $this->previous().$this->pages_render().$this->next(),
  209. $this->template['wrapper']
  210. );
  211. return $html;
  212. }
  213. /**
  214. * generate the HTML for the page links only
  215. *
  216. * @return string Markup for page number links
  217. */
  218. public function pages_render()
  219. {
  220. // no links if we only have one page
  221. if ($this->config['total_pages'] == 1)
  222. {
  223. return '';
  224. }
  225. $html = '';
  226. // let's get the starting page number, this is determined using num_links
  227. $start = (($this->config['current_page'] - $this->config['num_links']) > 0) ? $this->config['current_page'] - ($this->config['num_links'] - 1) : 1;
  228. // let's get the ending page number
  229. $end = (($this->config['current_page'] + $this->config['num_links']) < $this->config['total_pages']) ? $this->config['current_page'] + $this->config['num_links'] : $this->config['total_pages'];
  230. for($i = $start; $i <= $end; $i++)
  231. {
  232. if ($this->config['current_page'] == $i)
  233. {
  234. $html .= str_replace(
  235. '{link}',
  236. str_replace(array('{uri}', '{page}'), array('#', $i), $this->template['active-link']),
  237. $this->template['active']
  238. );
  239. }
  240. else
  241. {
  242. $url = ($i == 1) ? '' : '/'.$i;
  243. $html .= str_replace(
  244. '{link}',
  245. str_replace(array('{uri}', '{page}'), array(rtrim($this->config['pagination_url'], '/').$url, $i), $this->template['regular-link']),
  246. $this->template['regular']
  247. );
  248. }
  249. }
  250. return $html;
  251. }
  252. /**
  253. * Pagination "Previous" link
  254. *
  255. * @param string $value optional text to display in the link
  256. *
  257. * @return string Markup for the 'previous' page number link
  258. */
  259. public function previous($marker = '&laquo;')
  260. {
  261. $html = '';
  262. if ($this->config['total_pages'] > 1)
  263. {
  264. if ($this->config['current_page'] == 1)
  265. {
  266. $html = str_replace(
  267. '{link}',
  268. str_replace(array('{uri}', '{page}'), array('#', $marker), $this->template['previous-inactive-link']),
  269. $this->template['previous-inactive']
  270. );
  271. }
  272. else
  273. {
  274. $previous_page = $this->config['current_page'] - 1;
  275. $previous_page = ($previous_page == 1) ? '' : '/'.$previous_page;
  276. $html = str_replace(
  277. '{link}',
  278. str_replace(array('{uri}', '{page}'), array(rtrim($this->config['pagination_url'], '/').$previous_page, $marker), $this->template['previous-link']),
  279. $this->template['previous']
  280. );
  281. }
  282. }
  283. return $html;
  284. }
  285. /**
  286. * Pagination "Next" link
  287. *
  288. * @param string $value optional text to display in the link
  289. *
  290. * @return string Markup for the 'next' page number link
  291. */
  292. public function next($marker = '&raquo;')
  293. {
  294. $html = '';
  295. if ($this->config['total_pages'] > 1)
  296. {
  297. if ($this->config['current_page'] == $this->config['total_pages'])
  298. {
  299. $html = str_replace(
  300. '{link}',
  301. str_replace(array('{uri}', '{page}'), array('#', $marker), $this->template['next-inactive-link']),
  302. $this->template['next-inactive']
  303. );
  304. }
  305. else
  306. {
  307. $next_page = '/'.($this->config['current_page'] + 1);
  308. $html = str_replace(
  309. '{link}',
  310. str_replace(array('{uri}', '{page}'), array(rtrim($this->config['pagination_url'], '/').$next_page, $marker), $this->template['next-link']),
  311. $this->template['next']
  312. );
  313. }
  314. }
  315. return $html;
  316. }
  317. /**
  318. * Prepares vars for creating links
  319. */
  320. protected function _recalculate()
  321. {
  322. // calculate the number of pages
  323. $this->config['total_pages'] = ceil($this->config['total_items'] / $this->config['per_page']) ?: 1;
  324. // calculate the current page number
  325. $this->config['current_page'] = ($this->config['total_items'] > 0 and $this->config['current_page'] > 1) ? $this->config['current_page'] : (int) \Request::main()->uri->get_segment($this->config['uri_segment']);
  326. // make sure the current page is within bounds
  327. if ($this->config['current_page'] > $this->config['total_pages'])
  328. {
  329. $this->config['current_page'] = $this->config['total_pages'];
  330. }
  331. elseif ($this->config['current_page'] < 1)
  332. {
  333. $this->config['current_page'] = 1;
  334. }
  335. // the current page must be zero based so that the offset for page 1 is 0.
  336. $this->config['offset'] = ($this->config['current_page'] - 1) * $this->config['per_page'];
  337. }
  338. }