PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/libs/view/helpers/paginator.php

https://github.com/mariuz/firetube
PHP | 705 lines | 396 code | 49 blank | 260 comment | 100 complexity | 5acea4791585c78ef482e78c4fd44371 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * Pagination Helper class file.
  5. *
  6. * Generates pagination links
  7. *
  8. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  9. * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  10. *
  11. * Licensed under The MIT License
  12. * Redistributions of files must retain the above copyright notice.
  13. *
  14. * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
  15. * @link http://cakephp.org CakePHP(tm) Project
  16. * @package cake
  17. * @subpackage cake.cake.libs.view.helpers
  18. * @since CakePHP(tm) v 1.2.0
  19. * @version $Revision$
  20. * @modifiedby $LastChangedBy$
  21. * @lastmodified $Date$
  22. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  23. */
  24. /**
  25. * Pagination Helper class for easy generation of pagination links.
  26. *
  27. * PaginationHelper encloses all methods needed when working with pagination.
  28. *
  29. * @package cake
  30. * @subpackage cake.cake.libs.view.helpers
  31. */
  32. class PaginatorHelper extends AppHelper {
  33. /**
  34. * Helper dependencies
  35. *
  36. * @var array
  37. */
  38. var $helpers = array('Html', 'Ajax');
  39. /**
  40. * Holds the default model for paged recordsets
  41. *
  42. * @var string
  43. */
  44. var $__defaultModel = null;
  45. /**
  46. * Holds the default options for pagination links
  47. *
  48. * The values that may be specified are:
  49. *
  50. * - `$options['format']` Format of the counter. Supported formats are 'range' and 'pages'
  51. * and custom (default). In the default mode the supplied string is parsed and constants are replaced
  52. * by their actual values.
  53. * Constants: %page%, %pages%, %current%, %count%, %start%, %end% .
  54. * - `$options['separator']` The separator of the actual page and number of pages (default: ' of ').
  55. * - `$options['url']` Url of the action. See Router::url()
  56. * - `$options['url']['sort']` the key that the recordset is sorted.
  57. * - `$options['url']['direction']` Direction of the sorting (default: 'asc').
  58. * - `$options['url']['page']` Page # to display.
  59. * - `$options['model']` The name of the model.
  60. * - `$options['escape']` Defines if the title field for the link should be escaped (default: true).
  61. * - `$options['update']` DOM id of the element updated with the results of the AJAX call.
  62. * If this key isn't specified Paginator will use plain HTML links.
  63. * - `$options['indicator']` DOM id of the element that will be shown when doing AJAX requests.
  64. *
  65. * @var array
  66. */
  67. var $options = array();
  68. /**
  69. * Gets the current paging parameters from the resultset for the given model
  70. *
  71. * @param string $model Optional model name. Uses the default if none is specified.
  72. * @return array The array of paging parameters for the paginated resultset.
  73. */
  74. function params($model = null) {
  75. if (empty($model)) {
  76. $model = $this->defaultModel();
  77. }
  78. if (!isset($this->params['paging']) || empty($this->params['paging'][$model])) {
  79. return null;
  80. }
  81. return $this->params['paging'][$model];
  82. }
  83. /**
  84. * Sets default options for all pagination links
  85. *
  86. * @param mixed $options Default options for pagination links. If a string is supplied - it
  87. * is used as the DOM id element to update. See #options for list of keys.
  88. */
  89. function options($options = array()) {
  90. if (is_string($options)) {
  91. $options = array('update' => $options);
  92. }
  93. if (!empty($options['paging'])) {
  94. if (!isset($this->params['paging'])) {
  95. $this->params['paging'] = array();
  96. }
  97. $this->params['paging'] = array_merge($this->params['paging'], $options['paging']);
  98. unset($options['paging']);
  99. }
  100. $model = $this->defaultModel();
  101. if (!empty($options[$model])) {
  102. if (!isset($this->params['paging'][$model])) {
  103. $this->params['paging'][$model] = array();
  104. }
  105. $this->params['paging'][$model] = array_merge($this->params['paging'][$model], $options[$model]);
  106. unset($options[$model]);
  107. }
  108. $this->options = array_filter(array_merge($this->options, $options));
  109. }
  110. /**
  111. * Gets the current page of the recordset for the given model
  112. *
  113. * @param string $model Optional model name. Uses the default if none is specified.
  114. * @return string The current page number of the recordset.
  115. */
  116. function current($model = null) {
  117. $params = $this->params($model);
  118. if (isset($params['page'])) {
  119. return $params['page'];
  120. }
  121. return 1;
  122. }
  123. /**
  124. * Gets the current key by which the recordset is sorted
  125. *
  126. * @param string $model Optional model name. Uses the default if none is specified.
  127. * @param mixed $options Options for pagination links. See #options for list of keys.
  128. * @return string The name of the key by which the recordset is being sorted, or
  129. * null if the results are not currently sorted.
  130. */
  131. function sortKey($model = null, $options = array()) {
  132. if (empty($options)) {
  133. $params = $this->params($model);
  134. $options = array_merge($params['defaults'], $params['options']);
  135. }
  136. if (isset($options['sort']) && !empty($options['sort'])) {
  137. if (preg_match('/(?:\w+\.)?(\w+)/', $options['sort'], $result) && isset($result[1])) {
  138. if ($result[0] == $this->defaultModel()) {
  139. return $result[1];
  140. }
  141. }
  142. return $options['sort'];
  143. } elseif (isset($options['order']) && is_array($options['order'])) {
  144. return key($options['order']);
  145. } elseif (isset($options['order']) && is_string($options['order'])) {
  146. if (preg_match('/(?:\w+\.)?(\w+)/', $options['order'], $result) && isset($result[1])) {
  147. return $result[1];
  148. }
  149. return $options['order'];
  150. }
  151. return null;
  152. }
  153. /**
  154. * Gets the current direction the recordset is sorted
  155. *
  156. * @param string $model Optional model name. Uses the default if none is specified.
  157. * @param mixed $options Options for pagination links. See #options for list of keys.
  158. * @return string The direction by which the recordset is being sorted, or
  159. * null if the results are not currently sorted.
  160. */
  161. function sortDir($model = null, $options = array()) {
  162. $dir = null;
  163. if (empty($options)) {
  164. $params = $this->params($model);
  165. $options = array_merge($params['defaults'], $params['options']);
  166. }
  167. if (isset($options['direction'])) {
  168. $dir = strtolower($options['direction']);
  169. } elseif (isset($options['order']) && is_array($options['order'])) {
  170. $dir = strtolower(current($options['order']));
  171. }
  172. if ($dir == 'desc') {
  173. return 'desc';
  174. }
  175. return 'asc';
  176. }
  177. /**
  178. * Generates a "previous" link for a set of paged records
  179. *
  180. * Options:
  181. *
  182. * - `tag` The tag wrapping tag you want to use, defaults to 'span'
  183. * - `escape` Whether you want the contents html entity encoded, defaults to true
  184. * - `model` The model to use, defaults to PaginatorHelper::defaultModel()
  185. *
  186. * @param string $title Title for the link. Defaults to '<< Previous'.
  187. * @param mixed $options Options for pagination link. See #options for list of keys.
  188. * @param string $disabledTitle Title when the link is disabled.
  189. * @param mixed $disabledOptions Options for the disabled pagination link. See #options for list of keys.
  190. * @return string A "previous" link or $disabledTitle text if the link is disabled.
  191. */
  192. function prev($title = '<< Previous', $options = array(), $disabledTitle = null, $disabledOptions = array()) {
  193. return $this->__pagingLink('Prev', $title, $options, $disabledTitle, $disabledOptions);
  194. }
  195. /**
  196. * Generates a "next" link for a set of paged records
  197. *
  198. * Options:
  199. *
  200. * - `tag` The tag wrapping tag you want to use, defaults to 'span'
  201. * - `escape` Whether you want the contents html entity encoded, defaults to true
  202. * - `model` The model to use, defaults to PaginatorHelper::defaultModel()
  203. *
  204. * @param string $title Title for the link. Defaults to 'Next >>'.
  205. * @param mixed $options Options for pagination link. See above for list of keys.
  206. * @param string $disabledTitle Title when the link is disabled.
  207. * @param mixed $disabledOptions Options for the disabled pagination link. See above for list of keys.
  208. * @return string A "next" link or or $disabledTitle text if the link is disabled.
  209. */
  210. function next($title = 'Next >>', $options = array(), $disabledTitle = null, $disabledOptions = array()) {
  211. return $this->__pagingLink('Next', $title, $options, $disabledTitle, $disabledOptions);
  212. }
  213. /**
  214. * Generates a sorting link. Sets named parameters for the sort and direction. Handles
  215. * direction switching automatically.
  216. *
  217. * Options:
  218. *
  219. * - `escape` Whether you want the contents html entity encoded, defaults to true
  220. * - `model` The model to use, defaults to PaginatorHelper::defaultModel()
  221. *
  222. * @param string $title Title for the link.
  223. * @param string $key The name of the key that the recordset should be sorted. If $key is null
  224. * $title will be used for the key, and a title will be generated by inflection.
  225. * @param array $options Options for sorting link. See above for list of keys.
  226. * @return string A link sorting default by 'asc'. If the resultset is sorted 'asc' by the specified
  227. * key the returned link will sort by 'desc'.
  228. */
  229. function sort($title, $key = null, $options = array()) {
  230. $options = array_merge(array('url' => array(), 'model' => null), $options);
  231. $url = $options['url'];
  232. unset($options['url']);
  233. if (empty($key)) {
  234. $key = $title;
  235. $title = __(Inflector::humanize(preg_replace('/_id$/', '', $title)), true);
  236. }
  237. $dir = 'asc';
  238. $sortKey = $this->sortKey($options['model']);
  239. $isSorted = ($sortKey === $key || $sortKey === $this->defaultModel() . '.' . $key);
  240. if ($isSorted && $this->sortDir($options['model']) === 'asc') {
  241. $dir = 'desc';
  242. }
  243. if (is_array($title) && array_key_exists($dir, $title)) {
  244. $title = $title[$dir];
  245. }
  246. $url = array_merge(array('sort' => $key, 'direction' => $dir), $url, array('order' => null));
  247. return $this->link($title, $url, $options);
  248. }
  249. /**
  250. * Generates a plain or Ajax link with pagination parameters
  251. *
  252. * Options
  253. *
  254. * - `update` The Id of the DOM element you wish to update. Creates Ajax enabled links
  255. * with the AjaxHelper.
  256. * - `escape` Whether you want the contents html entity encoded, defaults to true
  257. * - `model` The model to use, defaults to PaginatorHelper::defaultModel()
  258. *
  259. * @param string $title Title for the link.
  260. * @param mixed $url Url for the action. See Router::url()
  261. * @param array $options Options for the link. See #options for list of keys.
  262. * @return string A link with pagination parameters.
  263. */
  264. function link($title, $url = array(), $options = array()) {
  265. $options = array_merge(array('model' => null, 'escape' => true), $options);
  266. $model = $options['model'];
  267. unset($options['model']);
  268. if (!empty($this->options)) {
  269. $options = array_merge($this->options, $options);
  270. }
  271. if (isset($options['url'])) {
  272. $url = array_merge((array)$options['url'], (array)$url);
  273. unset($options['url']);
  274. }
  275. $url = $this->url($url, true, $model);
  276. $obj = isset($options['update']) ? 'Ajax' : 'Html';
  277. $url = array_merge(array('page' => $this->current($model)), $url);
  278. $url = array_merge(Set::filter($url, true), array_intersect_key($url, array('plugin'=>true)));
  279. return $this->{$obj}->link($title, $url, $options);
  280. }
  281. /**
  282. * Merges passed URL options with current pagination state to generate a pagination URL.
  283. *
  284. * @param array $options Pagination/URL options array
  285. * @param boolean $asArray Return the url as an array, or a URI string
  286. * @param string $model Which model to paginate on
  287. * @return mixed By default, returns a full pagination URL string for use in non-standard contexts (i.e. JavaScript)
  288. */
  289. function url($options = array(), $asArray = false, $model = null) {
  290. $paging = $this->params($model);
  291. $url = array_merge(array_filter(Set::diff(array_merge($paging['defaults'], $paging['options']), $paging['defaults'])), $options);
  292. if (isset($url['order'])) {
  293. $sort = $direction = null;
  294. if (is_array($url['order'])) {
  295. list($sort, $direction) = array($this->sortKey($model, $url), current($url['order']));
  296. }
  297. unset($url['order']);
  298. $url = array_merge($url, compact('sort', 'direction'));
  299. }
  300. if ($asArray) {
  301. return $url;
  302. }
  303. return parent::url($url);
  304. }
  305. /**
  306. * Protected method for generating prev/next links
  307. *
  308. */
  309. function __pagingLink($which, $title = null, $options = array(), $disabledTitle = null, $disabledOptions = array()) {
  310. $check = 'has' . $which;
  311. $_defaults = array('url' => array(), 'step' => 1, 'escape' => true, 'model' => null, 'tag' => 'div');
  312. $options = array_merge($_defaults, (array)$options);
  313. $paging = $this->params($options['model']);
  314. if (!$this->{$check}($options['model']) && (!empty($disabledTitle) || !empty($disabledOptions))) {
  315. if (!empty($disabledTitle) && $disabledTitle !== true) {
  316. $title = $disabledTitle;
  317. }
  318. $options = array_merge($_defaults, (array)$disabledOptions);
  319. } elseif (!$this->{$check}($options['model'])) {
  320. return null;
  321. }
  322. foreach (array_keys($_defaults) as $key) {
  323. ${$key} = $options[$key];
  324. unset($options[$key]);
  325. }
  326. $url = array_merge(array('page' => $paging['page'] + ($which == 'Prev' ? $step * -1 : $step)), $url);
  327. if ($this->{$check}($model)) {
  328. return $this->link($title, $url, array_merge($options, array('escape' => $escape)));
  329. } else {
  330. return $this->Html->tag($tag, $title, $options, $escape);
  331. }
  332. }
  333. /**
  334. * Returns true if the given result set is not at the first page
  335. *
  336. * @param string $model Optional model name. Uses the default if none is specified.
  337. * @return boolean True if the result set is not at the first page.
  338. */
  339. function hasPrev($model = null) {
  340. return $this->__hasPage($model, 'prev');
  341. }
  342. /**
  343. * Returns true if the given result set is not at the last page
  344. *
  345. * @param string $model Optional model name. Uses the default if none is specified.
  346. * @return boolean True if the result set is not at the last page.
  347. */
  348. function hasNext($model = null) {
  349. return $this->__hasPage($model, 'next');
  350. }
  351. /**
  352. * Returns true if the given result set has the page number given by $page
  353. *
  354. * @param string $model Optional model name. Uses the default if none is specified.
  355. * @param int $page The page number - if not set defaults to 1.
  356. * @return boolean True if the given result set has the specified page number.
  357. */
  358. function hasPage($model = null, $page = 1) {
  359. if (is_numeric($model)) {
  360. $page = $model;
  361. $model = null;
  362. }
  363. $paging = $this->params($model);
  364. return $page <= $paging['pageCount'];
  365. }
  366. /**
  367. * Protected method
  368. *
  369. */
  370. function __hasPage($model, $page) {
  371. $params = $this->params($model);
  372. if (!empty($params)) {
  373. if ($params["{$page}Page"] == true) {
  374. return true;
  375. }
  376. }
  377. return false;
  378. }
  379. /**
  380. * Gets the default model of the paged sets
  381. *
  382. * @return string Model name or null if the pagination isn't initialized.
  383. */
  384. function defaultModel() {
  385. if ($this->__defaultModel != null) {
  386. return $this->__defaultModel;
  387. }
  388. if (empty($this->params['paging'])) {
  389. return null;
  390. }
  391. list($this->__defaultModel) = array_keys($this->params['paging']);
  392. return $this->__defaultModel;
  393. }
  394. /**
  395. * Returns a counter string for the paged result set
  396. *
  397. * Options
  398. *
  399. * - `model` The model to use, defaults to PaginatorHelper::defaultModel();
  400. * - `format` The format string you want to use, defaults to 'pages' Which generates output like '1 of 5'
  401. * set to 'range' to generate output like '1 - 3 of 13'. Can also be set to a custom string, containing
  402. * the following placeholders `%page%`, `%pages%`, `%current%`, `%count%`, `%start%`, `%end%` and any
  403. * custom content you would like.
  404. * - `separator` The separator string to use, default to ' of '
  405. *
  406. * @param mixed $options Options for the counter string. See #options for list of keys.
  407. * @return string Counter string.
  408. */
  409. function counter($options = array()) {
  410. if (is_string($options)) {
  411. $options = array('format' => $options);
  412. }
  413. $options = array_merge(
  414. array(
  415. 'model' => $this->defaultModel(),
  416. 'format' => 'pages',
  417. 'separator' => __(' of ', true)
  418. ),
  419. $options);
  420. $paging = $this->params($options['model']);
  421. if ($paging['pageCount'] == 0) {
  422. $paging['pageCount'] = 1;
  423. }
  424. $start = 0;
  425. if ($paging['count'] >= 1) {
  426. $start = (($paging['page'] - 1) * $paging['options']['limit']) + 1;
  427. }
  428. $end = $start + $paging['options']['limit'] - 1;
  429. if ($paging['count'] < $end) {
  430. $end = $paging['count'];
  431. }
  432. switch ($options['format']) {
  433. case 'range':
  434. if (!is_array($options['separator'])) {
  435. $options['separator'] = array(' - ', $options['separator']);
  436. }
  437. $out = $start . $options['separator'][0] . $end . $options['separator'][1] . $paging['count'];
  438. break;
  439. case 'pages':
  440. $out = $paging['page'] . $options['separator'] . $paging['pageCount'];
  441. break;
  442. default:
  443. $replace = array(
  444. '%page%' => $paging['page'],
  445. '%pages%' => $paging['pageCount'],
  446. '%current%' => $paging['current'],
  447. '%count%' => $paging['count'],
  448. '%start%' => $start,
  449. '%end%' => $end
  450. );
  451. $out = str_replace(array_keys($replace), array_values($replace), $options['format']);
  452. break;
  453. }
  454. return $this->output($out);
  455. }
  456. /**
  457. * Returns a set of numbers for the paged result set
  458. * uses a modulus to decide how many numbers to show on each side of the current page (default: 8)
  459. *
  460. * Options
  461. *
  462. * - `before` Content to be inserted before the numbers
  463. * - `after` Content to be inserted after the numbers
  464. * - `model` Model to create numbers for, defaults to PaginatorHelper::defaultModel()
  465. * - `modulus` how many numbers to include on either side of the current page, defaults to 8.
  466. * - `separator` Separator content defaults to ' | '
  467. * - `tag` The tag to wrap links in, defaults to 'span'
  468. * - `first` Whether you want first links generated, set to an integer to define the number of 'first'
  469. * links to generate
  470. * - `last` Whether you want last links generated, set to an integer to define the number of 'last'
  471. * links to generate
  472. *
  473. * @param mixed $options Options for the numbers, (before, after, model, modulus, separator)
  474. * @return string numbers string.
  475. */
  476. function numbers($options = array()) {
  477. if ($options === true) {
  478. $options = array(
  479. 'before' => ' | ', 'after' => ' | ',
  480. 'first' => 'first', 'last' => 'last',
  481. );
  482. }
  483. $options = array_merge(
  484. array(
  485. 'tag' => 'span',
  486. 'before'=> null, 'after'=> null,
  487. 'model' => $this->defaultModel(),
  488. 'modulus' => '8', 'separator' => ' | ',
  489. 'first' => null, 'last' => null,
  490. ),
  491. (array)$options);
  492. $params = array_merge(array('page'=> 1), (array)$this->params($options['model']));
  493. unset($options['model']);
  494. if ($params['pageCount'] <= 1) {
  495. return false;
  496. }
  497. extract($options);
  498. unset($options['tag'], $options['before'], $options['after'], $options['model'],
  499. $options['modulus'], $options['separator'], $options['first'], $options['last']);
  500. $out = '';
  501. if ($modulus && $params['pageCount'] > $modulus) {
  502. $half = intval($modulus / 2);
  503. $end = $params['page'] + $half;
  504. if ($end > $params['pageCount']) {
  505. $end = $params['pageCount'];
  506. }
  507. $start = $params['page'] - ($modulus - ($end - $params['page']));
  508. if ($start <= 1) {
  509. $start = 1;
  510. $end = $params['page'] + ($modulus - $params['page']) + 1;
  511. }
  512. if ($first && $start > 1) {
  513. $offset = ($start <= (int)$first) ? $start - 1 : $first;
  514. if ($offset < $start - 1) {
  515. $out .= $this->first($offset, array('tag' => $tag, 'separator' => $separator));
  516. } else {
  517. $out .= $this->first($offset, array('tag' => $tag, 'after' => $separator, 'separator' => $separator));
  518. }
  519. }
  520. $out .= $before;
  521. for ($i = $start; $i < $params['page']; $i++) {
  522. $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options)) . $separator;
  523. }
  524. $out .= $this->Html->tag($tag, $params['page'], array('class' => 'current'));
  525. if ($i != $params['pageCount']) {
  526. $out .= $separator;
  527. }
  528. $start = $params['page'] + 1;
  529. for ($i = $start; $i < $end; $i++) {
  530. $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options)). $separator;
  531. }
  532. if ($end != $params['page']) {
  533. $out .= $this->Html->tag($tag, $this->link($i, array('page' => $end), $options));
  534. }
  535. $out .= $after;
  536. if ($last && $end < $params['pageCount']) {
  537. $offset = ($params['pageCount'] < $end + (int)$last) ? $params['pageCount'] - $end : $last;
  538. if ($offset <= $last && $params['pageCount'] - $end > $offset) {
  539. $out .= $this->last($offset, array('tag' => $tag, 'separator' => $separator));
  540. } else {
  541. $out .= $this->last($offset, array('tag' => $tag, 'before' => $separator, 'separator' => $separator));
  542. }
  543. }
  544. } else {
  545. $out .= $before;
  546. for ($i = 1; $i <= $params['pageCount']; $i++) {
  547. if ($i == $params['page']) {
  548. $out .= $this->Html->tag($tag, $i, array('class' => 'current'));
  549. } else {
  550. $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options));
  551. }
  552. if ($i != $params['pageCount']) {
  553. $out .= $separator;
  554. }
  555. }
  556. $out .= $after;
  557. }
  558. return $this->output($out);
  559. }
  560. /**
  561. * Returns a first or set of numbers for the first pages
  562. *
  563. * Options:
  564. *
  565. * - `tag` The tag wrapping tag you want to use, defaults to 'span'
  566. * - `before` Content to insert before the link/tag
  567. * - `model` The model to use defaults to PaginatorHelper::defaultModel()
  568. * - `separator` Content between the generated links, defaults to ' | '
  569. *
  570. * @param mixed $first if string use as label for the link, if numeric print page numbers
  571. * @param mixed $options
  572. * @return string numbers string.
  573. */
  574. function first($first = '<< first', $options = array()) {
  575. $options = array_merge(
  576. array(
  577. 'tag' => 'span',
  578. 'after'=> null,
  579. 'model' => $this->defaultModel(),
  580. 'separator' => ' | ',
  581. ),
  582. (array)$options);
  583. $params = array_merge(array('page'=> 1), (array)$this->params($options['model']));
  584. unset($options['model']);
  585. if ($params['pageCount'] <= 1) {
  586. return false;
  587. }
  588. extract($options);
  589. unset($options['tag'], $options['after'], $options['model'], $options['separator']);
  590. $out = '';
  591. if (is_int($first) && $params['page'] > $first) {
  592. if ($after === null) {
  593. $after = '...';
  594. }
  595. for ($i = 1; $i <= $first; $i++) {
  596. $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options));
  597. if ($i != $first) {
  598. $out .= $separator;
  599. }
  600. }
  601. $out .= $after;
  602. } elseif ($params['page'] > 1) {
  603. $out = $this->Html->tag($tag, $this->link($first, array('page' => 1), $options)) . $after;
  604. }
  605. return $out;
  606. }
  607. /**
  608. * Returns a last or set of numbers for the last pages
  609. *
  610. * Options:
  611. *
  612. * - `tag` The tag wrapping tag you want to use, defaults to 'span'
  613. * - `before` Content to insert before the link/tag
  614. * - `model` The model to use defaults to PaginatorHelper::defaultModel()
  615. * - `separator` Content between the generated links, defaults to ' | '
  616. *
  617. * @param mixed $last if string use as label for the link, if numeric print page numbers
  618. * @param mixed $options Array of options
  619. * @return string numbers string.
  620. */
  621. function last($last = 'last >>', $options = array()) {
  622. $options = array_merge(
  623. array(
  624. 'tag' => 'span',
  625. 'before'=> null,
  626. 'model' => $this->defaultModel(),
  627. 'separator' => ' | ',
  628. ),
  629. (array)$options);
  630. $params = array_merge(array('page'=> 1), (array)$this->params($options['model']));
  631. unset($options['model']);
  632. if ($params['pageCount'] <= 1) {
  633. return false;
  634. }
  635. extract($options);
  636. unset($options['tag'], $options['before'], $options['model'], $options['separator']);
  637. $out = '';
  638. $lower = $params['pageCount'] - $last + 1;
  639. if (is_int($last) && $params['page'] < $lower) {
  640. if ($before === null) {
  641. $before = '...';
  642. }
  643. for ($i = $lower; $i <= $params['pageCount']; $i++) {
  644. $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options));
  645. if ($i != $params['pageCount']) {
  646. $out .= $separator;
  647. }
  648. }
  649. $out = $before . $out;
  650. } elseif ($params['page'] < $params['pageCount']) {
  651. $out = $before . $this->Html->tag($tag, $this->link($last, array('page' => $params['pageCount']), $options));
  652. }
  653. return $out;
  654. }
  655. }
  656. ?>