"Fossies" - the Fresh Open Source Software Archive

Member "grav/system/src/Grav/Framework/Pagination/AbstractPagination.php" (19 Mar 2020, 8353 Bytes) of package /linux/www/grav-v1.6.23.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "AbstractPagination.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 
    3 /**
    4  * @package    Grav\Framework\Pagination
    5  *
    6  * @copyright  Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
    7  * @license    MIT License; see LICENSE file for details.
    8  */
    9 
   10 namespace Grav\Framework\Pagination;
   11 
   12 use Grav\Framework\Pagination\Interfaces\PaginationInterface;
   13 use Grav\Framework\Route\Route;
   14 
   15 class AbstractPagination implements PaginationInterface
   16 {
   17     /** @var Route Base rouse used for the pagination. */
   18     protected $route;
   19 
   20     /** @var int|null  Current page. */
   21     protected $page;
   22 
   23     /** @var int|null  The record number to start displaying from. */
   24     protected $start;
   25 
   26     /** @var int  Number of records to display per page. */
   27     protected $limit;
   28 
   29     /** @var int  Total number of records. */
   30     protected $total;
   31 
   32     /** @var array Pagination options */
   33     protected $options;
   34 
   35     /** @var bool View all flag. */
   36     protected $viewAll;
   37 
   38     /** @var int  Total number of pages. */
   39     protected $pages;
   40 
   41     /** @var int  Value pagination object begins at. */
   42     protected $pagesStart;
   43 
   44     /** @var int  Value pagination object ends at .*/
   45     protected $pagesStop;
   46 
   47     /** @var array */
   48     protected $defaultOptions = [
   49         'type' => 'page',
   50         'limit' => 10,
   51         'display' => 5,
   52         'opening' => 0,
   53         'ending' => 0,
   54         'url' => null
   55     ];
   56 
   57     /** @var array */
   58     private $items;
   59 
   60     public function isEnabled(): bool
   61     {
   62         return $this->count() > 1;
   63     }
   64 
   65     public function getOptions(): array
   66     {
   67         return $this->options;
   68     }
   69 
   70     public function getRoute(): ?Route
   71     {
   72         return $this->route;
   73     }
   74 
   75     public function getTotalPages(): int
   76     {
   77         return $this->pages;
   78     }
   79 
   80     public function getPageNumber(): int
   81     {
   82         return $this->page;
   83     }
   84 
   85     public function getPrevNumber(int $count = 1): ?int
   86     {
   87         $page = $this->page - $count;
   88 
   89         return $page >= 1 ? $page : null;
   90     }
   91 
   92     public function getNextNumber(int $count = 1): ?int
   93     {
   94         $page = $this->page + $count;
   95 
   96         return $page <= $this->pages ? $page : null;
   97     }
   98 
   99     public function getPage(int $page, string $label = null): ?PaginationPage
  100     {
  101         if ($page < 1 || $page > $this->pages) {
  102             return null;
  103         }
  104 
  105         $start = ($page - 1) * $this->limit;
  106         if ($this->getOptions()['type'] === 'page') {
  107             $name = 'page';
  108             $offset = $page;
  109         } else {
  110             $name = 'start';
  111             $offset = $start;
  112         }
  113 
  114         return new PaginationPage(
  115             [
  116                 'label' => $label ?? (string)$page,
  117                 'number' => $page,
  118                 'offset_start' => $start,
  119                 'offset_end' => min($start + $this->limit, $this->total) - 1,
  120                 'enabled' => $page !== $this->page || $this->viewAll,
  121                 'active' => $page === $this->page,
  122                 'route' => $this->route->withGravParam($name, $offset)
  123             ]
  124         );
  125     }
  126 
  127     public function getFirstPage(string $label = null, int $count = 0): ?PaginationPage
  128     {
  129         return $this->getPage(1 + $count, $label ?? $this->getOptions()['label_first'] ?? null);
  130     }
  131 
  132     public function getPrevPage(string $label = null, int $count = 1): ?PaginationPage
  133     {
  134         return $this->getPage($this->page - $count, $label ?? $this->getOptions()['label_prev'] ?? null);
  135     }
  136 
  137     public function getNextPage(string $label = null, int $count = 1): ?PaginationPage
  138     {
  139         return $this->getPage($this->page + $count, $label ?? $this->getOptions()['label_next'] ?? null);
  140     }
  141 
  142     public function getLastPage(string $label = null, int $count = 0): ?PaginationPage
  143     {
  144         return $this->getPage($this->pages - $count, $label ?? $this->getOptions()['label_last'] ?? null);
  145     }
  146 
  147     public function getStart(): int
  148     {
  149         return $this->start;
  150     }
  151 
  152     public function getLimit(): int
  153     {
  154         return $this->limit;
  155     }
  156 
  157     public function getTotal(): int
  158     {
  159         return $this->total;
  160     }
  161 
  162     public function count(): int
  163     {
  164         $this->loadItems();
  165 
  166         return \count($this->items);
  167     }
  168 
  169     public function getIterator()
  170     {
  171         $this->loadItems();
  172 
  173         return new \ArrayIterator($this->items);
  174     }
  175 
  176     public function getPages(): array
  177     {
  178         $this->loadItems();
  179 
  180         return $this->items;
  181     }
  182 
  183     protected function loadItems()
  184     {
  185         $this->calculateRange();
  186 
  187         // Make list like: 1 ... 4 5 6 ... 10
  188         $range = range($this->pagesStart, $this->pagesStop);
  189         //$range[] = 1;
  190         //$range[] = $this->pages;
  191         natsort($range);
  192         $range = array_unique($range);
  193 
  194         $this->items = [];
  195         foreach ($range as $i) {
  196             $this->items[$i] = $this->getPage($i);
  197         }
  198     }
  199 
  200     protected function setRoute(Route $route)
  201     {
  202         $this->route = $route;
  203 
  204         return $this;
  205     }
  206 
  207     protected function setOptions(array $options = null)
  208     {
  209         $this->options = $options ? array_merge($this->defaultOptions, $options) : $this->defaultOptions;
  210 
  211         return $this;
  212     }
  213 
  214     protected function setPage(int $page = null)
  215     {
  216         $this->page = (int)max($page, 1);
  217         $this->start = null;
  218 
  219         return $this;
  220     }
  221 
  222     /**
  223      * @param int $start
  224      * @return $this
  225      */
  226     protected function setStart(int $start = null)
  227     {
  228         $this->start = (int)max($start, 0);
  229         $this->page = null;
  230 
  231         return $this;
  232     }
  233 
  234     /**
  235      * @param int|null $limit
  236      * @return $this
  237      */
  238     protected function setLimit(int $limit = null)
  239     {
  240         $this->limit = (int)max($limit ?? $this->getOptions()['limit'], 0);
  241 
  242         // No limit, display all records in a single page.
  243         $this->viewAll = !$limit;
  244 
  245         return $this;
  246     }
  247 
  248     /**
  249      * @param int $total
  250      * @return $this
  251      */
  252     protected function setTotal(int $total)
  253     {
  254         $this->total = (int)max($total, 0);
  255 
  256         return $this;
  257     }
  258 
  259     protected function initialize(Route $route, int $total, int $pos = null, int $limit = null, array $options = null)
  260     {
  261         $this->setRoute($route);
  262         $this->setOptions($options);
  263         $this->setTotal($total);
  264         if ($this->getOptions()['type'] === 'start') {
  265             $this->setStart($pos);
  266         } else {
  267             $this->setPage($pos);
  268         }
  269         $this->setLimit($limit);
  270         $this->calculateLimits();
  271     }
  272 
  273     protected function calculateLimits()
  274     {
  275         $limit = $this->limit;
  276         $total = $this->total;
  277 
  278         if (!$limit || $limit > $total) {
  279             // All records fit into a single page.
  280             $this->start = 0;
  281             $this->page = 1;
  282             $this->pages = 1;
  283 
  284             return;
  285         }
  286 
  287         if (null === $this->start) {
  288             // If we are using page, convert it to start.
  289             $this->start = (int)(($this->page - 1) * $limit);
  290         }
  291 
  292         if ($this->start > $total - $limit) {
  293             // If start is greater than total count (i.e. we are asked to display records that don't exist)
  294             // then set start to display the last natural page of results.
  295             $this->start = (int)max(0, (ceil($total / $limit) - 1) * $limit);
  296         }
  297 
  298         // Set the total pages and current page values.
  299         $this->page = (int)ceil(($this->start + 1) / $limit);
  300         $this->pages = (int)ceil($total / $limit);
  301     }
  302 
  303     protected function calculateRange()
  304     {
  305         $options = $this->getOptions();
  306         $displayed = $options['display'];
  307         $opening = $options['opening'];
  308         $ending = $options['ending'];
  309 
  310         // Set the pagination iteration loop values.
  311         $this->pagesStart = $this->page - (int)($displayed / 2);
  312         if ($this->pagesStart < 1 + $opening) {
  313             $this->pagesStart = 1 + $opening;
  314         }
  315         if ($this->pagesStart + $displayed - $opening > $this->pages) {
  316             $this->pagesStop = $this->pages;
  317             if ($this->pages < $displayed) {
  318                 $this->pagesStart = 1 + $opening;
  319             } else {
  320                 $this->pagesStart = $this->pages - $displayed + 1 + $opening;
  321             }
  322         } else {
  323             $this->pagesStop = (int)max(1, $this->pagesStart + $displayed - 1 - $ending);
  324         }
  325     }
  326 }