| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267 |
- <?php
- /**
- * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- * @link https://cakephp.org CakePHP(tm) Project
- * @since 1.2.0
- * @license https://opensource.org/licenses/mit-license.php MIT License
- */
- namespace Cake\View\Helper;
- use Cake\Utility\Hash;
- use Cake\Utility\Inflector;
- use Cake\View\Helper;
- use Cake\View\StringTemplateTrait;
- use Cake\View\View;
- /**
- * Pagination Helper class for easy generation of pagination links.
- *
- * PaginationHelper encloses all methods needed when working with pagination.
- *
- * @property \Cake\View\Helper\UrlHelper $Url
- * @property \Cake\View\Helper\NumberHelper $Number
- * @property \Cake\View\Helper\HtmlHelper $Html
- * @property \Cake\View\Helper\FormHelper $Form
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html
- */
- class PaginatorHelper extends Helper
- {
- use StringTemplateTrait;
- /**
- * List of helpers used by this helper
- *
- * @var array
- */
- public $helpers = ['Url', 'Number', 'Html', 'Form'];
- /**
- * Default config for this class
- *
- * Options: Holds the default options for pagination links
- *
- * The values that may be specified are:
- *
- * - `url` Url of the action. See Router::url()
- * - `url['sort']` the key that the recordset is sorted.
- * - `url['direction']` Direction of the sorting (default: 'asc').
- * - `url['page']` Page number to use in links.
- * - `model` The name of the model.
- * - `escape` Defines if the title field for the link should be escaped (default: true).
- *
- * Templates: the templates used by this class
- *
- * @var array
- */
- protected $_defaultConfig = [
- 'options' => [],
- 'templates' => [
- 'nextActive' => '<li class="next"><a rel="next" href="{{url}}">{{text}}</a></li>',
- 'nextDisabled' => '<li class="next disabled"><a href="" onclick="return false;">{{text}}</a></li>',
- 'prevActive' => '<li class="prev"><a rel="prev" href="{{url}}">{{text}}</a></li>',
- 'prevDisabled' => '<li class="prev disabled"><a href="" onclick="return false;">{{text}}</a></li>',
- 'counterRange' => '{{start}} - {{end}} of {{count}}',
- 'counterPages' => '{{page}} of {{pages}}',
- 'first' => '<li class="first"><a href="{{url}}">{{text}}</a></li>',
- 'last' => '<li class="last"><a href="{{url}}">{{text}}</a></li>',
- 'number' => '<li><a href="{{url}}">{{text}}</a></li>',
- 'current' => '<li class="active"><a href="">{{text}}</a></li>',
- 'ellipsis' => '<li class="ellipsis">…</li>',
- 'sort' => '<a href="{{url}}">{{text}}</a>',
- 'sortAsc' => '<a class="asc" href="{{url}}">{{text}}</a>',
- 'sortDesc' => '<a class="desc" href="{{url}}">{{text}}</a>',
- 'sortAscLocked' => '<a class="asc locked" href="{{url}}">{{text}}</a>',
- 'sortDescLocked' => '<a class="desc locked" href="{{url}}">{{text}}</a>',
- ]
- ];
- /**
- * Default model of the paged sets
- *
- * @var string
- */
- protected $_defaultModel;
- /**
- * Constructor. Overridden to merge passed args with URL options.
- *
- * @param \Cake\View\View $View The View this helper is being attached to.
- * @param array $config Configuration settings for the helper.
- */
- public function __construct(View $View, array $config = [])
- {
- parent::__construct($View, $config);
- $query = $this->_View->getRequest()->getQueryParams();
- unset($query['page'], $query['limit'], $query['sort'], $query['direction']);
- $this->setConfig(
- 'options.url',
- array_merge($this->_View->getRequest()->getParam('pass', []), ['?' => $query])
- );
- }
- /**
- * Gets the current paging parameters from the resultset for the given model
- *
- * @param string|null $model Optional model name. Uses the default if none is specified.
- * @return array The array of paging parameters for the paginated resultset.
- */
- public function params($model = null)
- {
- $request = $this->_View->getRequest();
- if (empty($model)) {
- $model = $this->defaultModel();
- }
- if (!$request->getParam('paging') || !$request->getParam('paging.' . $model)) {
- return [];
- }
- return $request->getParam('paging.' . $model);
- }
- /**
- * Convenience access to any of the paginator params.
- *
- * @param string $key Key of the paginator params array to retrieve.
- * @param string|null $model Optional model name. Uses the default if none is specified.
- * @return mixed Content of the requested param.
- */
- public function param($key, $model = null)
- {
- $params = $this->params($model);
- if (!isset($params[$key])) {
- return null;
- }
- return $params[$key];
- }
- /**
- * Sets default options for all pagination links
- *
- * @param array $options Default options for pagination links.
- * See PaginatorHelper::$options for list of keys.
- * @return void
- */
- public function options(array $options = [])
- {
- $request = $this->_View->getRequest();
- if (!empty($options['paging'])) {
- $request = $request->withParam(
- 'paging',
- $options['paging'] + $request->getParam('paging', [])
- );
- unset($options['paging']);
- }
- $model = $this->defaultModel();
- if (!empty($options[$model])) {
- $request = $request->withParam(
- 'paging.' . $model,
- $options[$model] + (array)$request->getParam('paging.' . $model, [])
- );
- unset($options[$model]);
- }
- $this->_View->setRequest($request);
- $this->_config['options'] = array_filter($options + $this->_config['options']);
- if (empty($this->_config['options']['url'])) {
- $this->_config['options']['url'] = [];
- }
- if (!empty($this->_config['options']['model'])) {
- $this->defaultModel($this->_config['options']['model']);
- }
- }
- /**
- * Gets the current page of the recordset for the given model
- *
- * @param string|null $model Optional model name. Uses the default if none is specified.
- * @return int The current page number of the recordset.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#checking-the-pagination-state
- */
- public function current($model = null)
- {
- $params = $this->params($model);
- if (isset($params['page'])) {
- return $params['page'];
- }
- return 1;
- }
- /**
- * Gets the total number of pages in the recordset for the given model.
- *
- * @param string|null $model Optional model name. Uses the default if none is specified.
- * @return int The total pages for the recordset.
- */
- public function total($model = null)
- {
- $params = $this->params($model);
- if (isset($params['pageCount'])) {
- return $params['pageCount'];
- }
- return 0;
- }
- /**
- * Gets the current key by which the recordset is sorted
- *
- * @param string|null $model Optional model name. Uses the default if none is specified.
- * @param array $options Options for pagination links. See #options for list of keys.
- * @return string|null The name of the key by which the recordset is being sorted, or
- * null if the results are not currently sorted.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-sort-links
- */
- public function sortKey($model = null, array $options = [])
- {
- if (empty($options)) {
- $options = $this->params($model);
- }
- if (!empty($options['sort'])) {
- return $options['sort'];
- }
- return null;
- }
- /**
- * Gets the current direction the recordset is sorted
- *
- * @param string|null $model Optional model name. Uses the default if none is specified.
- * @param array $options Options for pagination links. See #options for list of keys.
- * @return string The direction by which the recordset is being sorted, or
- * null if the results are not currently sorted.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-sort-links
- */
- public function sortDir($model = null, array $options = [])
- {
- $dir = null;
- if (empty($options)) {
- $options = $this->params($model);
- }
- if (isset($options['direction'])) {
- $dir = strtolower($options['direction']);
- }
- if ($dir === 'desc') {
- return 'desc';
- }
- return 'asc';
- }
- /**
- * Generate an active/inactive link for next/prev methods.
- *
- * @param string|bool $text The enabled text for the link.
- * @param bool $enabled Whether or not the enabled/disabled version should be created.
- * @param array $options An array of options from the calling method.
- * @param array $templates An array of templates with the 'active' and 'disabled' keys.
- * @return string Generated HTML
- */
- protected function _toggledLink($text, $enabled, $options, $templates)
- {
- $template = $templates['active'];
- if (!$enabled) {
- $text = $options['disabledTitle'];
- $template = $templates['disabled'];
- }
- if (!$enabled && $text === false) {
- return '';
- }
- $text = $options['escape'] ? h($text) : $text;
- $templater = $this->templater();
- $newTemplates = !empty($options['templates']) ? $options['templates'] : false;
- if ($newTemplates) {
- $templater->push();
- $templateMethod = is_string($options['templates']) ? 'load' : 'add';
- $templater->{$templateMethod}($options['templates']);
- }
- if (!$enabled) {
- $out = $templater->format($template, [
- 'text' => $text,
- ]);
- if ($newTemplates) {
- $templater->pop();
- }
- return $out;
- }
- $paging = $this->params($options['model']);
- $url = array_merge(
- $options['url'],
- ['page' => $paging['page'] + $options['step']]
- );
- $url = $this->generateUrl($url, $options['model']);
- $out = $templater->format($template, [
- 'url' => $url,
- 'text' => $text,
- ]);
- if ($newTemplates) {
- $templater->pop();
- }
- return $out;
- }
- /**
- * Generates a "previous" link for a set of paged records
- *
- * ### Options:
- *
- * - `disabledTitle` The text to used when the link is disabled. This
- * defaults to the same text at the active link. Setting to false will cause
- * this method to return ''.
- * - `escape` Whether you want the contents html entity encoded, defaults to true
- * - `model` The model to use, defaults to PaginatorHelper::defaultModel()
- * - `url` An array of additional URL options to use for link generation.
- * - `templates` An array of templates, or template file name containing the
- * templates you'd like to use when generating the link for previous page.
- * The helper's original templates will be restored once prev() is done.
- *
- * @param string $title Title for the link. Defaults to '<< Previous'.
- * @param array $options Options for pagination link. See above for list of keys.
- * @return string A "previous" link or a disabled link.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-jump-links
- */
- public function prev($title = '<< Previous', array $options = [])
- {
- $defaults = [
- 'url' => [],
- 'model' => $this->defaultModel(),
- 'disabledTitle' => $title,
- 'escape' => true,
- ];
- $options += $defaults;
- $options['step'] = -1;
- $enabled = $this->hasPrev($options['model']);
- $templates = [
- 'active' => 'prevActive',
- 'disabled' => 'prevDisabled'
- ];
- return $this->_toggledLink($title, $enabled, $options, $templates);
- }
- /**
- * Generates a "next" link for a set of paged records
- *
- * ### Options:
- *
- * - `disabledTitle` The text to used when the link is disabled. This
- * defaults to the same text at the active link. Setting to false will cause
- * this method to return ''.
- * - `escape` Whether you want the contents html entity encoded, defaults to true
- * - `model` The model to use, defaults to PaginatorHelper::defaultModel()
- * - `url` An array of additional URL options to use for link generation.
- * - `templates` An array of templates, or template file name containing the
- * templates you'd like to use when generating the link for next page.
- * The helper's original templates will be restored once next() is done.
- *
- * @param string $title Title for the link. Defaults to 'Next >>'.
- * @param array $options Options for pagination link. See above for list of keys.
- * @return string A "next" link or $disabledTitle text if the link is disabled.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-jump-links
- */
- public function next($title = 'Next >>', array $options = [])
- {
- $defaults = [
- 'url' => [],
- 'model' => $this->defaultModel(),
- 'disabledTitle' => $title,
- 'escape' => true,
- ];
- $options += $defaults;
- $options['step'] = 1;
- $enabled = $this->hasNext($options['model']);
- $templates = [
- 'active' => 'nextActive',
- 'disabled' => 'nextDisabled'
- ];
- return $this->_toggledLink($title, $enabled, $options, $templates);
- }
- /**
- * Generates a sorting link. Sets named parameters for the sort and direction. Handles
- * direction switching automatically.
- *
- * ### Options:
- *
- * - `escape` Whether you want the contents html entity encoded, defaults to true.
- * - `model` The model to use, defaults to PaginatorHelper::defaultModel().
- * - `direction` The default direction to use when this link isn't active.
- * - `lock` Lock direction. Will only use the default direction then, defaults to false.
- *
- * @param string $key The name of the key that the recordset should be sorted.
- * @param string|null $title Title for the link. If $title is null $key will be used
- * for the title and will be generated by inflection.
- * @param array $options Options for sorting link. See above for list of keys.
- * @return string A link sorting default by 'asc'. If the resultset is sorted 'asc' by the specified
- * key the returned link will sort by 'desc'.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-sort-links
- */
- public function sort($key, $title = null, array $options = [])
- {
- $options += ['url' => [], 'model' => null, 'escape' => true];
- $url = $options['url'];
- unset($options['url']);
- if (empty($title)) {
- $title = $key;
- if (strpos($title, '.') !== false) {
- $title = str_replace('.', ' ', $title);
- }
- $title = __(Inflector::humanize(preg_replace('/_id$/', '', $title)));
- }
- $defaultDir = isset($options['direction']) ? strtolower($options['direction']) : 'asc';
- unset($options['direction']);
- $locked = isset($options['lock']) ? $options['lock'] : false;
- unset($options['lock']);
- $sortKey = $this->sortKey($options['model']);
- $defaultModel = $this->defaultModel();
- $model = $options['model'] ?: $defaultModel;
- list($table, $field) = explode('.', $key . '.');
- if (!$field) {
- $field = $table;
- $table = $model;
- }
- $isSorted = (
- $sortKey === $table . '.' . $field ||
- $sortKey === $model . '.' . $key ||
- $table . '.' . $field === $model . '.' . $sortKey
- );
- $template = 'sort';
- $dir = $defaultDir;
- if ($isSorted) {
- if ($locked) {
- $template = $dir === 'asc' ? 'sortDescLocked' : 'sortAscLocked';
- } else {
- $dir = $this->sortDir($options['model']) === 'asc' ? 'desc' : 'asc';
- $template = $dir === 'asc' ? 'sortDesc' : 'sortAsc';
- }
- }
- if (is_array($title) && array_key_exists($dir, $title)) {
- $title = $title[$dir];
- }
- $url = array_merge(
- ['sort' => $key, 'direction' => $dir, 'page' => 1],
- $url,
- ['order' => null]
- );
- $vars = [
- 'text' => $options['escape'] ? h($title) : $title,
- 'url' => $this->generateUrl($url, $options['model']),
- ];
- return $this->templater()->format($template, $vars);
- }
- /**
- * Merges passed URL options with current pagination state to generate a pagination URL.
- *
- * ### Url options:
- *
- * - `escape`: If false, the URL will be returned unescaped, do only use if it is manually
- * escaped afterwards before being displayed.
- * - `fullBase`: If true, the full base URL will be prepended to the result
- *
- * @param array $options Pagination/URL options array
- * @param string|null $model Which model to paginate on
- * @param array $urlOptions Array of options
- * The bool version of this argument is *deprecated* and will be removed in 4.0.0
- * @return string By default, returns a full pagination URL string for use in non-standard contexts (i.e. JavaScript)
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#generating-pagination-urls
- */
- public function generateUrl(array $options = [], $model = null, $urlOptions = [])
- {
- if (is_bool($urlOptions)) {
- $urlOptions = ['fullBase' => $urlOptions];
- deprecationWarning(
- 'Passing a boolean value as third argument into PaginatorHelper::generateUrl() is deprecated ' .
- 'and will be removed in 4.0.0 . ' .
- 'Pass an array instead.'
- );
- }
- $urlOptions += [
- 'escape' => true,
- 'fullBase' => false
- ];
- return $this->Url->build($this->generateUrlParams($options, $model), $urlOptions);
- }
- /**
- * Merges passed URL options with current pagination state to generate a pagination URL.
- *
- * @param array $options Pagination/URL options array
- * @param string|null $model Which model to paginate on
- * @return array An array of URL parameters
- */
- public function generateUrlParams(array $options = [], $model = null)
- {
- $paging = $this->params($model);
- $paging += ['page' => null, 'sort' => null, 'direction' => null, 'limit' => null];
- if (!empty($paging['sort']) && !empty($options['sort']) && strpos($options['sort'], '.') === false) {
- $paging['sort'] = $this->_removeAlias($paging['sort'], $model = null);
- }
- if (!empty($paging['sortDefault']) && !empty($options['sort']) && strpos($options['sort'], '.') === false) {
- $paging['sortDefault'] = $this->_removeAlias($paging['sortDefault'], $model);
- }
- $url = [
- 'page' => $paging['page'],
- 'limit' => $paging['limit'],
- 'sort' => $paging['sort'],
- 'direction' => $paging['direction'],
- ];
- if (!empty($this->_config['options']['url'])) {
- $key = implode('.', array_filter(['options.url', Hash::get($paging, 'scope', null)]));
- $url = array_merge($url, Hash::get($this->_config, $key, []));
- }
- $url = array_filter($url, function ($value) {
- return ($value || is_numeric($value) || $value === false);
- });
- $url = array_merge($url, $options);
- if (!empty($url['page']) && $url['page'] == 1) {
- $url['page'] = false;
- }
- if (isset($paging['sortDefault'], $paging['directionDefault'], $url['sort'], $url['direction']) &&
- $url['sort'] === $paging['sortDefault'] &&
- strtolower($url['direction']) === strtolower($paging['directionDefault'])
- ) {
- $url['sort'] = $url['direction'] = null;
- }
- if (!empty($paging['scope'])) {
- $scope = $paging['scope'];
- $currentParams = $this->_config['options']['url'];
- if (isset($url['#'])) {
- $currentParams['#'] = $url['#'];
- unset($url['#']);
- }
- // Merge existing query parameters in the scope.
- if (isset($currentParams['?'][$scope]) && is_array($currentParams['?'][$scope])) {
- $url += $currentParams['?'][$scope];
- unset($currentParams['?'][$scope]);
- }
- $url = [$scope => $url] + $currentParams;
- if (empty($url[$scope]['page'])) {
- unset($url[$scope]['page']);
- }
- }
- return $url;
- }
- /**
- * Remove alias if needed.
- *
- * @param string $field Current field
- * @param string|null $model Current model alias
- * @return string Unaliased field if applicable
- */
- protected function _removeAlias($field, $model = null)
- {
- $currentModel = $model ?: $this->defaultModel();
- if (strpos($field, '.') === false) {
- return $field;
- }
- list ($alias, $currentField) = explode('.', $field);
- if ($alias === $currentModel) {
- return $currentField;
- }
- return $field;
- }
- /**
- * Returns true if the given result set is not at the first page
- *
- * @param string|null $model Optional model name. Uses the default if none is specified.
- * @return bool True if the result set is not at the first page.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#checking-the-pagination-state
- */
- public function hasPrev($model = null)
- {
- return $this->_hasPage($model, 'prev');
- }
- /**
- * Returns true if the given result set is not at the last page
- *
- * @param string|null $model Optional model name. Uses the default if none is specified.
- * @return bool True if the result set is not at the last page.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#checking-the-pagination-state
- */
- public function hasNext($model = null)
- {
- return $this->_hasPage($model, 'next');
- }
- /**
- * Returns true if the given result set has the page number given by $page
- *
- * @param string|null $model Optional model name. Uses the default if none is specified.
- * @param int $page The page number - if not set defaults to 1.
- * @return bool True if the given result set has the specified page number.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#checking-the-pagination-state
- */
- public function hasPage($model = null, $page = 1)
- {
- if (is_numeric($model)) {
- $page = $model;
- $model = null;
- }
- $paging = $this->params($model);
- if ($paging === []) {
- return false;
- }
- return $page <= $paging['pageCount'];
- }
- /**
- * Does $model have $page in its range?
- *
- * @param string $model Model name to get parameters for.
- * @param int $page Page number you are checking.
- * @return bool Whether model has $page
- */
- protected function _hasPage($model, $page)
- {
- $params = $this->params($model);
- return !empty($params) && $params[$page . 'Page'];
- }
- /**
- * Gets or sets the default model of the paged sets
- *
- * @param string|null $model Model name to set
- * @return string|null Model name or null if the pagination isn't initialized.
- */
- public function defaultModel($model = null)
- {
- if ($model !== null) {
- $this->_defaultModel = $model;
- }
- if ($this->_defaultModel) {
- return $this->_defaultModel;
- }
- if (!$this->_View->getRequest()->getParam('paging')) {
- return null;
- }
- list($this->_defaultModel) = array_keys($this->_View->getRequest()->getParam('paging'));
- return $this->_defaultModel;
- }
- /**
- * Returns a counter string for the paged result set
- *
- * ### Options
- *
- * - `model` The model to use, defaults to PaginatorHelper::defaultModel();
- * - `format` The format string you want to use, defaults to 'pages' Which generates output like '1 of 5'
- * set to 'range' to generate output like '1 - 3 of 13'. Can also be set to a custom string, containing
- * the following placeholders `{{page}}`, `{{pages}}`, `{{current}}`, `{{count}}`, `{{model}}`, `{{start}}`, `{{end}}` and any
- * custom content you would like.
- *
- * @param string|array $options Options for the counter string. See #options for list of keys.
- * If string it will be used as format.
- * @return string Counter string.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-a-page-counter
- */
- public function counter($options = [])
- {
- if (is_string($options)) {
- $options = ['format' => $options];
- }
- $options += [
- 'model' => $this->defaultModel(),
- 'format' => 'pages',
- ];
- $paging = $this->params($options['model']);
- if (!$paging['pageCount']) {
- $paging['pageCount'] = 1;
- }
- switch ($options['format']) {
- case 'range':
- case 'pages':
- $template = 'counter' . ucfirst($options['format']);
- break;
- default:
- $template = 'counterCustom';
- $this->templater()->add([$template => $options['format']]);
- }
- $map = array_map([$this->Number, 'format'], [
- 'page' => $paging['page'],
- 'pages' => $paging['pageCount'],
- 'current' => $paging['current'],
- 'count' => $paging['count'],
- 'start' => $paging['start'],
- 'end' => $paging['end']
- ]);
- $map += [
- 'model' => strtolower(Inflector::humanize(Inflector::tableize($options['model'])))
- ];
- return $this->templater()->format($template, $map);
- }
- /**
- * Returns a set of numbers for the paged result set
- * uses a modulus to decide how many numbers to show on each side of the current page (default: 8).
- *
- * ```
- * $this->Paginator->numbers(['first' => 2, 'last' => 2]);
- * ```
- *
- * Using the first and last options you can create links to the beginning and end of the page set.
- *
- * ### Options
- *
- * - `before` Content to be inserted before the numbers, but after the first links.
- * - `after` Content to be inserted after the numbers, but before the last links.
- * - `model` Model to create numbers for, defaults to PaginatorHelper::defaultModel()
- * - `modulus` How many numbers to include on either side of the current page, defaults to 8.
- * Set to `false` to disable and to show all numbers.
- * - `first` Whether you want first links generated, set to an integer to define the number of 'first'
- * links to generate. If a string is set a link to the first page will be generated with the value
- * as the title.
- * - `last` Whether you want last links generated, set to an integer to define the number of 'last'
- * links to generate. If a string is set a link to the last page will be generated with the value
- * as the title.
- * - `templates` An array of templates, or template file name containing the templates you'd like to
- * use when generating the numbers. The helper's original templates will be restored once
- * numbers() is done.
- * - `url` An array of additional URL options to use for link generation.
- *
- * The generated number links will include the 'ellipsis' template when the `first` and `last` options
- * and the number of pages exceed the modulus. For example if you have 25 pages, and use the first/last
- * options and a modulus of 8, ellipsis content will be inserted after the first and last link sets.
- *
- * @param array $options Options for the numbers.
- * @return string|false Numbers string.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-page-number-links
- */
- public function numbers(array $options = [])
- {
- $defaults = [
- 'before' => null, 'after' => null, 'model' => $this->defaultModel(),
- 'modulus' => 8, 'first' => null, 'last' => null, 'url' => []
- ];
- $options += $defaults;
- $params = (array)$this->params($options['model']) + ['page' => 1];
- if ($params['pageCount'] <= 1) {
- return false;
- }
- $templater = $this->templater();
- if (isset($options['templates'])) {
- $templater->push();
- $method = is_string($options['templates']) ? 'load' : 'add';
- $templater->{$method}($options['templates']);
- }
- if ($options['modulus'] !== false && $params['pageCount'] > $options['modulus']) {
- $out = $this->_modulusNumbers($templater, $params, $options);
- } else {
- $out = $this->_numbers($templater, $params, $options);
- }
- if (isset($options['templates'])) {
- $templater->pop();
- }
- return $out;
- }
- /**
- * Calculates the start and end for the pagination numbers.
- *
- * @param array $params Params from the numbers() method.
- * @param array $options Options from the numbers() method.
- * @return array An array with the start and end numbers.
- */
- protected function _getNumbersStartAndEnd($params, $options)
- {
- $half = (int)($options['modulus'] / 2);
- $end = max(1 + $options['modulus'], $params['page'] + $half);
- $start = min($params['pageCount'] - $options['modulus'], $params['page'] - $half - $options['modulus'] % 2);
- if ($options['first']) {
- $first = is_int($options['first']) ? $options['first'] : 1;
- if ($start <= $first + 2) {
- $start = 1;
- }
- }
- if ($options['last']) {
- $last = is_int($options['last']) ? $options['last'] : 1;
- if ($end >= $params['pageCount'] - $last - 1) {
- $end = $params['pageCount'];
- }
- }
- $end = min($params['pageCount'], $end);
- $start = max(1, $start);
- return [$start, $end];
- }
- /**
- * Formats a number for the paginator number output.
- *
- * @param \Cake\View\StringTemplate $templater StringTemplate instance.
- * @param array $options Options from the numbers() method.
- * @return string
- */
- protected function _formatNumber($templater, $options)
- {
- $url = array_merge($options['url'], ['page' => $options['page']]);
- $vars = [
- 'text' => $options['text'],
- 'url' => $this->generateUrl($url, $options['model']),
- ];
- return $templater->format('number', $vars);
- }
- /**
- * Generates the numbers for the paginator numbers() method.
- *
- * @param \Cake\View\StringTemplate $templater StringTemplate instance.
- * @param array $params Params from the numbers() method.
- * @param array $options Options from the numbers() method.
- * @return string Markup output.
- */
- protected function _modulusNumbers($templater, $params, $options)
- {
- $out = '';
- $ellipsis = $templater->format('ellipsis', []);
- list($start, $end) = $this->_getNumbersStartAndEnd($params, $options);
- $out .= $this->_firstNumber($ellipsis, $params, $start, $options);
- $out .= $options['before'];
- for ($i = $start; $i < $params['page']; $i++) {
- $out .= $this->_formatNumber($templater, [
- 'text' => $this->Number->format($i),
- 'page' => $i,
- 'model' => $options['model'],
- 'url' => $options['url'],
- ]);
- }
- $url = array_merge($options['url'], ['page' => $params['page']]);
- $out .= $templater->format('current', [
- 'text' => $this->Number->format($params['page']),
- 'url' => $this->generateUrl($url, $options['model']),
- ]);
- $start = $params['page'] + 1;
- $i = $start;
- while ($i < $end) {
- $out .= $this->_formatNumber($templater, [
- 'text' => $this->Number->format($i),
- 'page' => $i,
- 'model' => $options['model'],
- 'url' => $options['url'],
- ]);
- $i++;
- }
- if ($end != $params['page']) {
- $out .= $this->_formatNumber($templater, [
- 'text' => $this->Number->format($i),
- 'page' => $end,
- 'model' => $options['model'],
- 'url' => $options['url'],
- ]);
- }
- $out .= $options['after'];
- $out .= $this->_lastNumber($ellipsis, $params, $end, $options);
- return $out;
- }
- /**
- * Generates the first number for the paginator numbers() method.
- *
- * @param string $ellipsis Ellipsis character.
- * @param array $params Params from the numbers() method.
- * @param int $start Start number.
- * @param array $options Options from the numbers() method.
- * @return string Markup output.
- */
- protected function _firstNumber($ellipsis, $params, $start, $options)
- {
- $out = '';
- $first = is_int($options['first']) ? $options['first'] : 0;
- if ($options['first'] && $start > 1) {
- $offset = ($start <= $first) ? $start - 1 : $options['first'];
- $out .= $this->first($offset, $options);
- if ($first < $start - 1) {
- $out .= $ellipsis;
- }
- }
- return $out;
- }
- /**
- * Generates the last number for the paginator numbers() method.
- *
- * @param string $ellipsis Ellipsis character.
- * @param array $params Params from the numbers() method.
- * @param int $end End number.
- * @param array $options Options from the numbers() method.
- * @return string Markup output.
- */
- protected function _lastNumber($ellipsis, $params, $end, $options)
- {
- $out = '';
- $last = is_int($options['last']) ? $options['last'] : 0;
- if ($options['last'] && $end < $params['pageCount']) {
- $offset = ($params['pageCount'] < $end + $last) ? $params['pageCount'] - $end : $options['last'];
- if ($offset <= $options['last'] && $params['pageCount'] - $end > $last) {
- $out .= $ellipsis;
- }
- $out .= $this->last($offset, $options);
- }
- return $out;
- }
- /**
- * Generates the numbers for the paginator numbers() method.
- *
- * @param \Cake\View\StringTemplate $templater StringTemplate instance.
- * @param array $params Params from the numbers() method.
- * @param array $options Options from the numbers() method.
- * @return string Markup output.
- */
- protected function _numbers($templater, $params, $options)
- {
- $out = '';
- $out .= $options['before'];
- for ($i = 1; $i <= $params['pageCount']; $i++) {
- $url = array_merge($options['url'], ['page' => $i]);
- if ($i == $params['page']) {
- $out .= $templater->format('current', [
- 'text' => $this->Number->format($params['page']),
- 'url' => $this->generateUrl($url, $options['model']),
- ]);
- } else {
- $vars = [
- 'text' => $this->Number->format($i),
- 'url' => $this->generateUrl($url, $options['model']),
- ];
- $out .= $templater->format('number', $vars);
- }
- }
- $out .= $options['after'];
- return $out;
- }
- /**
- * Returns a first or set of numbers for the first pages.
- *
- * ```
- * echo $this->Paginator->first('< first');
- * ```
- *
- * Creates a single link for the first page. Will output nothing if you are on the first page.
- *
- * ```
- * echo $this->Paginator->first(3);
- * ```
- *
- * Will create links for the first 3 pages, once you get to the third or greater page. Prior to that
- * nothing will be output.
- *
- * ### Options:
- *
- * - `model` The model to use defaults to PaginatorHelper::defaultModel()
- * - `escape` Whether or not to HTML escape the text.
- * - `url` An array of additional URL options to use for link generation.
- *
- * @param string|int $first if string use as label for the link. If numeric, the number of page links
- * you want at the beginning of the range.
- * @param array $options An array of options.
- * @return string|false Numbers string.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-jump-links
- */
- public function first($first = '<< first', array $options = [])
- {
- $options += [
- 'url' => [],
- 'model' => $this->defaultModel(),
- 'escape' => true
- ];
- $params = $this->params($options['model']);
- if ($params['pageCount'] <= 1) {
- return false;
- }
- $out = '';
- if (is_int($first) && $params['page'] >= $first) {
- for ($i = 1; $i <= $first; $i++) {
- $url = array_merge($options['url'], ['page' => $i]);
- $out .= $this->templater()->format('number', [
- 'url' => $this->generateUrl($url, $options['model']),
- 'text' => $this->Number->format($i)
- ]);
- }
- } elseif ($params['page'] > 1 && is_string($first)) {
- $first = $options['escape'] ? h($first) : $first;
- $out .= $this->templater()->format('first', [
- 'url' => $this->generateUrl(['page' => 1], $options['model']),
- 'text' => $first
- ]);
- }
- return $out;
- }
- /**
- * Returns a last or set of numbers for the last pages.
- *
- * ```
- * echo $this->Paginator->last('last >');
- * ```
- *
- * Creates a single link for the last page. Will output nothing if you are on the last page.
- *
- * ```
- * echo $this->Paginator->last(3);
- * ```
- *
- * Will create links for the last 3 pages. Once you enter the page range, no output will be created.
- *
- * ### Options:
- *
- * - `model` The model to use defaults to PaginatorHelper::defaultModel()
- * - `escape` Whether or not to HTML escape the text.
- * - `url` An array of additional URL options to use for link generation.
- *
- * @param string|int $last if string use as label for the link, if numeric print page numbers
- * @param array $options Array of options
- * @return string|false Numbers string.
- * @link https://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-jump-links
- */
- public function last($last = 'last >>', array $options = [])
- {
- $options += [
- 'model' => $this->defaultModel(),
- 'escape' => true,
- 'url' => []
- ];
- $params = $this->params($options['model']);
- if ($params['pageCount'] <= 1) {
- return false;
- }
- $out = '';
- $lower = (int)$params['pageCount'] - (int)$last + 1;
- if (is_int($last) && $params['page'] <= $lower) {
- for ($i = $lower; $i <= $params['pageCount']; $i++) {
- $url = array_merge($options['url'], ['page' => $i]);
- $out .= $this->templater()->format('number', [
- 'url' => $this->generateUrl($url, $options['model']),
- 'text' => $this->Number->format($i)
- ]);
- }
- } elseif ($params['page'] < $params['pageCount'] && is_string($last)) {
- $last = $options['escape'] ? h($last) : $last;
- $out .= $this->templater()->format('last', [
- 'url' => $this->generateUrl(['page' => $params['pageCount']], $options['model']),
- 'text' => $last
- ]);
- }
- return $out;
- }
- /**
- * Returns the meta-links for a paginated result set.
- *
- * ```
- * echo $this->Paginator->meta();
- * ```
- *
- * Echos the links directly, will output nothing if there is neither a previous nor next page.
- *
- * ```
- * $this->Paginator->meta(['block' => true]);
- * ```
- *
- * Will append the output of the meta function to the named block - if true is passed the "meta"
- * block is used.
- *
- * ### Options:
- *
- * - `model` The model to use defaults to PaginatorHelper::defaultModel()
- * - `block` The block name to append the output to, or false/absent to return as a string
- * - `prev` (default True) True to generate meta for previous page
- * - `next` (default True) True to generate meta for next page
- * - `first` (default False) True to generate meta for first page
- * - `last` (default False) True to generate meta for last page
- *
- * @param array $options Array of options
- * @return string|null Meta links
- */
- public function meta(array $options = [])
- {
- $options += [
- 'model' => null,
- 'block' => false,
- 'prev' => true,
- 'next' => true,
- 'first' => false,
- 'last' => false
- ];
- $model = isset($options['model']) ? $options['model'] : null;
- $params = $this->params($model);
- $links = [];
- if ($options['prev'] && $this->hasPrev()) {
- $links[] = $this->Html->meta('prev', $this->generateUrl(['page' => $params['page'] - 1], null, ['fullBase' => true]));
- }
- if ($options['next'] && $this->hasNext()) {
- $links[] = $this->Html->meta('next', $this->generateUrl(['page' => $params['page'] + 1], null, ['fullBase' => true]));
- }
- if ($options['first']) {
- $links[] = $this->Html->meta('first', $this->generateUrl(['page' => 1], null, ['fullBase' => true]));
- }
- if ($options['last']) {
- $links[] = $this->Html->meta('last', $this->generateUrl(['page' => $params['pageCount']], null, ['fullBase' => true]));
- }
- $out = implode($links);
- if ($options['block'] === true) {
- $options['block'] = __FUNCTION__;
- }
- if ($options['block']) {
- $this->_View->append($options['block'], $out);
- return null;
- }
- return $out;
- }
- /**
- * Event listeners.
- *
- * @return array
- */
- public function implementedEvents()
- {
- return [];
- }
- /**
- * Dropdown select for pagination limit.
- * This will generate a wrapping form.
- *
- * @param array $limits The options array.
- * @param int|null $default Default option for pagination limit. Defaults to `$this->param('perPage')`.
- * @param array $options Options for Select tag attributes like class, id or event
- * @return string html output.
- */
- public function limitControl(array $limits = [], $default = null, array $options = [])
- {
- $out = $this->Form->create(null, ['type' => 'get']);
- if (empty($default) || !is_numeric($default)) {
- $default = $this->param('perPage');
- }
- if (empty($limits)) {
- $limits = [
- '20' => '20',
- '50' => '50',
- '100' => '100'
- ];
- }
- $out .= $this->Form->control('limit', $options + [
- 'type' => 'select',
- 'label' => __('View'),
- 'value' => $default,
- 'options' => $limits,
- 'onChange' => 'this.form.submit()'
- ]);
- $out .= $this->Form->end();
- return $out;
- }
- }
|