[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Joomla! Content Management System 5 * 6 * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> 7 * @license GNU General Public License version 2 or later; see LICENSE.txt 8 */ 9 10 namespace Joomla\CMS\Pagination; 11 12 use Joomla\CMS\Application\CMSApplication; 13 use Joomla\CMS\Factory; 14 use Joomla\CMS\HTML\HTMLHelper; 15 use Joomla\CMS\Language\Text; 16 use Joomla\CMS\Layout\LayoutHelper; 17 use Joomla\CMS\Router\Route; 18 19 // phpcs:disable PSR1.Files.SideEffects 20 \defined('JPATH_PLATFORM') or die; 21 // phpcs:enable PSR1.Files.SideEffects 22 23 /** 24 * Pagination Class. Provides a common interface for content pagination for the Joomla! CMS. 25 * 26 * @since 1.5 27 */ 28 class Pagination 29 { 30 /** 31 * @var integer The record number to start displaying from. 32 * @since 1.5 33 */ 34 public $limitstart = null; 35 36 /** 37 * @var integer Number of rows to display per page. 38 * @since 1.5 39 */ 40 public $limit = null; 41 42 /** 43 * @var integer Total number of rows. 44 * @since 1.5 45 */ 46 public $total = null; 47 48 /** 49 * @var integer Prefix used for request variables. 50 * @since 1.6 51 */ 52 public $prefix = null; 53 54 /** 55 * @var integer Value pagination object begins at 56 * @since 3.0 57 */ 58 public $pagesStart; 59 60 /** 61 * @var integer Value pagination object ends at 62 * @since 3.0 63 */ 64 public $pagesStop; 65 66 /** 67 * @var integer Current page 68 * @since 3.0 69 */ 70 public $pagesCurrent; 71 72 /** 73 * @var integer Total number of pages 74 * @since 3.0 75 */ 76 public $pagesTotal; 77 78 /** 79 * @var boolean The flag indicates whether to add limitstart=0 to URL 80 * @since 3.9.0 81 */ 82 public $hideEmptyLimitstart = false; 83 84 /** 85 * @var boolean View all flag 86 * @since 3.0 87 */ 88 protected $viewall = false; 89 90 /** 91 * Additional URL parameters to be added to the pagination URLs generated by the class. These 92 * may be useful for filters and extra values when dealing with lists and GET requests. 93 * 94 * @var array 95 * @since 3.0 96 */ 97 protected $additionalUrlParams = array(); 98 99 /** 100 * @var CMSApplication The application object 101 * @since 3.4 102 */ 103 protected $app = null; 104 105 /** 106 * Pagination data object 107 * 108 * @var object 109 * @since 3.4 110 */ 111 protected $data; 112 113 /** 114 * Constructor. 115 * 116 * @param integer $total The total number of items. 117 * @param integer $limitstart The offset of the item to start at. 118 * @param integer $limit The number of items to display per page. 119 * @param string $prefix The prefix used for request variables. 120 * @param CMSApplication $app The application object 121 * 122 * @since 1.5 123 */ 124 public function __construct($total, $limitstart, $limit, $prefix = '', CMSApplication $app = null) 125 { 126 // Value/type checking. 127 $this->total = (int) $total; 128 $this->limitstart = (int) max($limitstart, 0); 129 $this->limit = (int) max($limit, 0); 130 $this->prefix = $prefix; 131 $this->app = $app ?: Factory::getApplication(); 132 133 if ($this->limit > $this->total) { 134 $this->limitstart = 0; 135 } 136 137 if (!$this->limit) { 138 $this->limit = $total; 139 $this->limitstart = 0; 140 } 141 142 /* 143 * If limitstart is greater than total (i.e. we are asked to display records that don't exist) 144 * then set limitstart to display the last natural page of results 145 */ 146 if ($this->limitstart > $this->total - $this->limit) { 147 $this->limitstart = max(0, (int) (ceil($this->total / $this->limit) - 1) * $this->limit); 148 } 149 150 // Set the total pages and current page values. 151 if ($this->limit > 0) { 152 $this->pagesTotal = (int) ceil($this->total / $this->limit); 153 $this->pagesCurrent = (int) ceil(($this->limitstart + 1) / $this->limit); 154 } 155 156 // Set the pagination iteration loop values. 157 $displayedPages = 10; 158 $this->pagesStart = $this->pagesCurrent - ($displayedPages / 2); 159 160 if ($this->pagesStart < 1) { 161 $this->pagesStart = 1; 162 } 163 164 if ($this->pagesStart + $displayedPages > $this->pagesTotal) { 165 $this->pagesStop = $this->pagesTotal; 166 167 if ($this->pagesTotal < $displayedPages) { 168 $this->pagesStart = 1; 169 } else { 170 $this->pagesStart = $this->pagesTotal - $displayedPages + 1; 171 } 172 } else { 173 $this->pagesStop = $this->pagesStart + $displayedPages - 1; 174 } 175 176 // If we are viewing all records set the view all flag to true. 177 if ($limit === 0) { 178 $this->viewall = true; 179 } 180 } 181 182 /** 183 * Method to set an additional URL parameter to be added to all pagination class generated 184 * links. 185 * 186 * @param string $key The name of the URL parameter for which to set a value. 187 * @param mixed $value The value to set for the URL parameter. 188 * 189 * @return mixed The old value for the parameter. 190 * 191 * @since 1.6 192 */ 193 public function setAdditionalUrlParam($key, $value) 194 { 195 // Get the old value to return and set the new one for the URL parameter. 196 $result = $this->additionalUrlParams[$key] ?? null; 197 198 // If the passed parameter value is null unset the parameter, otherwise set it to the given value. 199 if ($value === null) { 200 unset($this->additionalUrlParams[$key]); 201 } else { 202 $this->additionalUrlParams[$key] = $value; 203 } 204 205 return $result; 206 } 207 208 /** 209 * Method to get an additional URL parameter (if it exists) to be added to 210 * all pagination class generated links. 211 * 212 * @param string $key The name of the URL parameter for which to get the value. 213 * 214 * @return mixed The value if it exists or null if it does not. 215 * 216 * @since 1.6 217 */ 218 public function getAdditionalUrlParam($key) 219 { 220 return $this->additionalUrlParams[$key] ?? null; 221 } 222 223 /** 224 * Return the rationalised offset for a row with a given index. 225 * 226 * @param integer $index The row index 227 * 228 * @return integer Rationalised offset for a row with a given index. 229 * 230 * @since 1.5 231 */ 232 public function getRowOffset($index) 233 { 234 return $index + 1 + $this->limitstart; 235 } 236 237 /** 238 * Return the pagination data object, only creating it if it doesn't already exist. 239 * 240 * @return \stdClass Pagination data object. 241 * 242 * @since 1.5 243 */ 244 public function getData() 245 { 246 if (!$this->data) { 247 $this->data = $this->_buildDataObject(); 248 } 249 250 return $this->data; 251 } 252 253 /** 254 * Create and return the pagination pages counter string, ie. Page 2 of 4. 255 * 256 * @return string Pagination pages counter string. 257 * 258 * @since 1.5 259 */ 260 public function getPagesCounter() 261 { 262 $html = null; 263 264 if ($this->pagesTotal > 1) { 265 $html .= Text::sprintf('JLIB_HTML_PAGE_CURRENT_OF_TOTAL', $this->pagesCurrent, $this->pagesTotal); 266 } 267 268 return $html; 269 } 270 271 /** 272 * Create and return the pagination result set counter string, e.g. Results 1-10 of 42 273 * 274 * @return string Pagination result set counter string. 275 * 276 * @since 1.5 277 */ 278 public function getResultsCounter() 279 { 280 $html = null; 281 $fromResult = $this->limitstart + 1; 282 283 // If the limit is reached before the end of the list. 284 if ($this->limitstart + $this->limit < $this->total) { 285 $toResult = $this->limitstart + $this->limit; 286 } else { 287 $toResult = $this->total; 288 } 289 290 // If there are results found. 291 if ($this->total > 0) { 292 $msg = Text::sprintf('JLIB_HTML_RESULTS_OF', $fromResult, $toResult, $this->total); 293 $html .= "\n" . $msg; 294 } else { 295 $html .= "\n" . Text::_('JLIB_HTML_NO_RECORDS_FOUND'); 296 } 297 298 return $html; 299 } 300 301 /** 302 * Create and return the pagination page list string, ie. Previous, Next, 1 2 3 ... x. 303 * 304 * @return string Pagination page list string. 305 * 306 * @since 1.5 307 */ 308 public function getPagesLinks() 309 { 310 // Build the page navigation list. 311 $data = $this->_buildDataObject(); 312 313 $list = array(); 314 $list['prefix'] = $this->prefix; 315 316 $chromePath = JPATH_THEMES . '/' . $this->app->getTemplate() . '/html/pagination.php'; 317 318 if (is_file($chromePath)) { 319 include_once $chromePath; 320 } 321 322 // Build the select list 323 if ($data->all->base !== null) { 324 $list['all']['active'] = true; 325 $list['all']['data'] = $this->_item_active($data->all); 326 } else { 327 $list['all']['active'] = false; 328 $list['all']['data'] = $this->_item_inactive($data->all); 329 } 330 331 if ($data->start->base !== null) { 332 $list['start']['active'] = true; 333 $list['start']['data'] = $this->_item_active($data->start); 334 } else { 335 $list['start']['active'] = false; 336 $list['start']['data'] = $this->_item_inactive($data->start); 337 } 338 339 if ($data->previous->base !== null) { 340 $list['previous']['active'] = true; 341 $list['previous']['data'] = $this->_item_active($data->previous); 342 } else { 343 $list['previous']['active'] = false; 344 $list['previous']['data'] = $this->_item_inactive($data->previous); 345 } 346 347 // Make sure it exists 348 $list['pages'] = array(); 349 350 foreach ($data->pages as $i => $page) { 351 if ($page->base !== null) { 352 $list['pages'][$i]['active'] = true; 353 $list['pages'][$i]['data'] = $this->_item_active($page); 354 } else { 355 $list['pages'][$i]['active'] = false; 356 $list['pages'][$i]['data'] = $this->_item_inactive($page); 357 } 358 } 359 360 if ($data->next->base !== null) { 361 $list['next']['active'] = true; 362 $list['next']['data'] = $this->_item_active($data->next); 363 } else { 364 $list['next']['active'] = false; 365 $list['next']['data'] = $this->_item_inactive($data->next); 366 } 367 368 if ($data->end->base !== null) { 369 $list['end']['active'] = true; 370 $list['end']['data'] = $this->_item_active($data->end); 371 } else { 372 $list['end']['active'] = false; 373 $list['end']['data'] = $this->_item_inactive($data->end); 374 } 375 376 if ($this->total > $this->limit) { 377 return $this->_list_render($list); 378 } else { 379 return ''; 380 } 381 } 382 383 /** 384 * Get the pagination links 385 * 386 * @param string $layoutId Layout to render the links 387 * @param array $options Optional array with settings for the layout 388 * 389 * @return string Pagination links. 390 * 391 * @since 3.3 392 */ 393 public function getPaginationLinks($layoutId = 'joomla.pagination.links', $options = array()) 394 { 395 // Allow to receive a null layout 396 $layoutId = $layoutId ?? 'joomla.pagination.links'; 397 398 $list = array( 399 'prefix' => $this->prefix, 400 'limit' => $this->limit, 401 'limitstart' => $this->limitstart, 402 'total' => $this->total, 403 'limitfield' => $this->getLimitBox(), 404 'pagescounter' => $this->getPagesCounter(), 405 'pages' => $this->getPaginationPages(), 406 'pagesTotal' => $this->pagesTotal, 407 ); 408 409 return LayoutHelper::render($layoutId, array('list' => $list, 'options' => $options)); 410 } 411 412 /** 413 * Create and return the pagination pages list, ie. Previous, Next, 1 2 3 ... x. 414 * 415 * @return array Pagination pages list. 416 * 417 * @since 3.3 418 */ 419 public function getPaginationPages() 420 { 421 $list = array(); 422 423 if ($this->total > $this->limit) { 424 // Build the page navigation list. 425 $data = $this->_buildDataObject(); 426 427 // All 428 $list['all']['active'] = $data->all->base !== null; 429 $list['all']['data'] = $data->all; 430 431 // Start 432 $list['start']['active'] = $data->start->base !== null; 433 $list['start']['data'] = $data->start; 434 435 // Previous link 436 $list['previous']['active'] = $data->previous->base !== null; 437 $list['previous']['data'] = $data->previous; 438 439 // Make sure it exists 440 $list['pages'] = array(); 441 442 foreach ($data->pages as $i => $page) { 443 $list['pages'][$i]['active'] = $page->base !== null; 444 $list['pages'][$i]['data'] = $page; 445 } 446 447 $list['next']['active'] = $data->next->base !== null; 448 $list['next']['data'] = $data->next; 449 450 $list['end']['active'] = $data->end->base !== null; 451 $list['end']['data'] = $data->end; 452 } 453 454 return $list; 455 } 456 457 /** 458 * Return the pagination footer. 459 * 460 * @return string Pagination footer. 461 * 462 * @since 1.5 463 */ 464 public function getListFooter() 465 { 466 // Keep B/C for overrides done with chromes 467 $chromePath = JPATH_THEMES . '/' . $this->app->getTemplate() . '/html/pagination.php'; 468 469 if (is_file($chromePath)) { 470 include_once $chromePath; 471 472 if (\function_exists('pagination_list_footer')) { 473 @trigger_error( 474 'pagination_list_footer is deprecated. Use the layout joomla.pagination.links instead.', 475 E_USER_DEPRECATED 476 ); 477 478 $list = array( 479 'prefix' => $this->prefix, 480 'limit' => $this->limit, 481 'limitstart' => $this->limitstart, 482 'total' => $this->total, 483 'limitfield' => $this->getLimitBox(), 484 'pagescounter' => $this->getPagesCounter(), 485 'pageslinks' => $this->getPagesLinks(), 486 ); 487 488 return pagination_list_footer($list); 489 } 490 } 491 492 return $this->getPaginationLinks(); 493 } 494 495 /** 496 * Creates a dropdown box for selecting how many records to show per page. 497 * 498 * @return string The HTML for the limit # input box. 499 * 500 * @since 1.5 501 */ 502 public function getLimitBox() 503 { 504 $limits = array(); 505 506 // Make the option list. 507 for ($i = 5; $i <= 30; $i += 5) { 508 $limits[] = HTMLHelper::_('select.option', "$i"); 509 } 510 511 $limits[] = HTMLHelper::_('select.option', '50', Text::_('J50')); 512 $limits[] = HTMLHelper::_('select.option', '100', Text::_('J100')); 513 $limits[] = HTMLHelper::_('select.option', '0', Text::_('JALL')); 514 515 $selected = $this->viewall ? 0 : $this->limit; 516 517 // Build the select list. 518 if ($this->app->isClient('administrator')) { 519 $html = HTMLHelper::_( 520 'select.genericlist', 521 $limits, 522 $this->prefix . 'limit', 523 'class="form-select" onchange="Joomla.submitform();"', 524 'value', 525 'text', 526 $selected 527 ); 528 } else { 529 $html = HTMLHelper::_( 530 'select.genericlist', 531 $limits, 532 $this->prefix . 'limit', 533 'class="form-select" onchange="this.form.submit()"', 534 'value', 535 'text', 536 $selected 537 ); 538 } 539 540 return $html; 541 } 542 543 /** 544 * Return the icon to move an item UP. 545 * 546 * @param integer $i The row index. 547 * @param boolean $condition True to show the icon. 548 * @param string $task The task to fire. 549 * @param string $alt The image alternative text string. 550 * @param boolean $enabled An optional setting for access control on the action. 551 * @param string $checkbox An optional prefix for checkboxes. 552 * 553 * @return string Either the icon to move an item up or a space. 554 * 555 * @since 1.5 556 */ 557 public function orderUpIcon($i, $condition = true, $task = 'orderup', $alt = 'JLIB_HTML_MOVE_UP', $enabled = true, $checkbox = 'cb') 558 { 559 if (($i > 0 || ($i + $this->limitstart > 0)) && $condition) { 560 return HTMLHelper::_('jgrid.orderUp', $i, $task, '', $alt, $enabled, $checkbox); 561 } else { 562 return ' '; 563 } 564 } 565 566 /** 567 * Return the icon to move an item DOWN. 568 * 569 * @param integer $i The row index. 570 * @param integer $n The number of items in the list. 571 * @param boolean $condition True to show the icon. 572 * @param string $task The task to fire. 573 * @param string $alt The image alternative text string. 574 * @param boolean $enabled An optional setting for access control on the action. 575 * @param string $checkbox An optional prefix for checkboxes. 576 * 577 * @return string Either the icon to move an item down or a space. 578 * 579 * @since 1.5 580 */ 581 public function orderDownIcon($i, $n, $condition = true, $task = 'orderdown', $alt = 'JLIB_HTML_MOVE_DOWN', $enabled = true, $checkbox = 'cb') 582 { 583 if (($i < $n - 1 || $i + $this->limitstart < $this->total - 1) && $condition) { 584 return HTMLHelper::_('jgrid.orderDown', $i, $task, '', $alt, $enabled, $checkbox); 585 } else { 586 return ' '; 587 } 588 } 589 590 /** 591 * Create the HTML for a list footer 592 * 593 * @param array $list Pagination list data structure. 594 * 595 * @return string HTML for a list footer 596 * 597 * @since 1.5 598 */ 599 protected function _list_footer($list) 600 { 601 $html = "<div class=\"list-footer\">\n"; 602 603 $html .= "\n<div class=\"limit\">" . Text::_('JGLOBAL_DISPLAY_NUM') . $list['limitfield'] . "</div>"; 604 $html .= $list['pageslinks']; 605 $html .= "\n<div class=\"counter\">" . $list['pagescounter'] . "</div>"; 606 607 $html .= "\n<input type=\"hidden\" name=\"" . $list['prefix'] . "limitstart\" value=\"" . $list['limitstart'] . "\">"; 608 $html .= "\n</div>"; 609 610 return $html; 611 } 612 613 /** 614 * Create the html for a list footer 615 * 616 * @param array $list Pagination list data structure. 617 * 618 * @return string HTML for a list start, previous, next,end 619 * 620 * @since 1.5 621 */ 622 protected function _list_render($list) 623 { 624 return LayoutHelper::render('joomla.pagination.list', array('list' => $list)); 625 } 626 627 /** 628 * Method to create an active pagination link to the item 629 * 630 * @param PaginationObject $item The object with which to make an active link. 631 * 632 * @return string HTML link 633 * 634 * @since 1.5 635 */ 636 protected function _item_active(PaginationObject $item) 637 { 638 return LayoutHelper::render('joomla.pagination.link', ['data' => $item, 'active' => true]); 639 } 640 641 /** 642 * Method to create an inactive pagination string 643 * 644 * @param PaginationObject $item The item to be processed 645 * 646 * @return string 647 * 648 * @since 1.5 649 */ 650 protected function _item_inactive(PaginationObject $item) 651 { 652 return LayoutHelper::render('joomla.pagination.link', ['data' => $item, 'active' => false]); 653 } 654 655 /** 656 * Create and return the pagination data object. 657 * 658 * @return \stdClass Pagination data object. 659 * 660 * @since 1.5 661 */ 662 protected function _buildDataObject() 663 { 664 $data = new \stdClass(); 665 666 // Build the additional URL parameters string. 667 $params = ''; 668 669 if (!empty($this->additionalUrlParams)) { 670 foreach ($this->additionalUrlParams as $key => $value) { 671 $params .= '&' . $key . '=' . $value; 672 } 673 } 674 675 $data->all = new PaginationObject(Text::_('JLIB_HTML_VIEW_ALL'), $this->prefix); 676 677 if (!$this->viewall) { 678 $data->all->base = '0'; 679 $data->all->link = Route::_($params . '&' . $this->prefix . 'limitstart='); 680 } 681 682 // Set the start and previous data objects. 683 $data->start = new PaginationObject(Text::_('JLIB_HTML_START'), $this->prefix); 684 $data->previous = new PaginationObject(Text::_('JPREV'), $this->prefix); 685 686 if ($this->pagesCurrent > 1) { 687 $page = ($this->pagesCurrent - 2) * $this->limit; 688 689 if ($this->hideEmptyLimitstart) { 690 $data->start->link = Route::_($params . '&' . $this->prefix . 'limitstart='); 691 } else { 692 $data->start->link = Route::_($params . '&' . $this->prefix . 'limitstart=0'); 693 } 694 695 $data->start->base = '0'; 696 $data->previous->base = $page; 697 698 if ($page === 0 && $this->hideEmptyLimitstart) { 699 $data->previous->link = $data->start->link; 700 } else { 701 $data->previous->link = Route::_($params . '&' . $this->prefix . 'limitstart=' . $page); 702 } 703 } 704 705 // Set the next and end data objects. 706 $data->next = new PaginationObject(Text::_('JNEXT'), $this->prefix); 707 $data->end = new PaginationObject(Text::_('JLIB_HTML_END'), $this->prefix); 708 709 if ($this->pagesCurrent < $this->pagesTotal) { 710 $next = $this->pagesCurrent * $this->limit; 711 $end = ($this->pagesTotal - 1) * $this->limit; 712 713 $data->next->base = $next; 714 $data->next->link = Route::_($params . '&' . $this->prefix . 'limitstart=' . $next); 715 $data->end->base = $end; 716 $data->end->link = Route::_($params . '&' . $this->prefix . 'limitstart=' . $end); 717 } 718 719 $data->pages = array(); 720 $stop = $this->pagesStop; 721 722 for ($i = $this->pagesStart; $i <= $stop; $i++) { 723 $offset = ($i - 1) * $this->limit; 724 725 $data->pages[$i] = new PaginationObject($i, $this->prefix); 726 727 if ($i != $this->pagesCurrent || $this->viewall) { 728 $data->pages[$i]->base = $offset; 729 730 if ($offset === 0 && $this->hideEmptyLimitstart) { 731 $data->pages[$i]->link = $data->start->link; 732 } else { 733 $data->pages[$i]->link = Route::_($params . '&' . $this->prefix . 'limitstart=' . $offset); 734 } 735 } else { 736 $data->pages[$i]->active = true; 737 } 738 } 739 740 return $data; 741 } 742 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |