]> git.mxchange.org Git - friendica.git/commitdiff
Add new Content\Pager class
authorHypolite Petovan <hypolite@mrpetovan.com>
Wed, 24 Oct 2018 06:07:21 +0000 (02:07 -0400)
committerHypolite Petovan <hypolite@mrpetovan.com>
Thu, 25 Oct 2018 04:07:15 +0000 (00:07 -0400)
src/Content/Pager.php [new file with mode: 0644]

diff --git a/src/Content/Pager.php b/src/Content/Pager.php
new file mode 100644 (file)
index 0000000..185c550
--- /dev/null
@@ -0,0 +1,295 @@
+<?php
+
+namespace Friendica\Content;
+
+use Friendica\Core\L10n;
+
+/**
+ * The Pager has two very different output, Minimal and Full, see renderMinimal() and renderFull() for more details.
+ *
+ * @author Hypolite Petovan <mrpetovan@gmail.com>
+ */
+class Pager
+{
+       /**
+        * @var integer
+        */
+       private $page = 1;
+       /**
+        * @var integer
+        */
+       private $itemsPerPage = 50;
+       /**
+        * @var integer
+        */
+       private $itemCount = 0;
+
+       /**
+        * @var string
+        */
+       private $baseQueryString = '';
+
+       /**
+        * Instantiates a new Pager with the base parameters.
+        *
+        * Guesses the page number from the GET parameter 'page'.
+        *
+        * @param string  $queryString  The query string of the current page
+        * @param integer $itemCount    The total item count (for the full mode) or null (for the minimal mode)
+        * @param integer $itemsPerPage An optional number of items per page to override the default value
+        */
+       public function __construct($queryString, $itemCount = null, $itemsPerPage = 50)
+       {
+               $this->setQueryString($queryString);
+               $this->setItemsPerPage($itemsPerPage);
+               $this->setItemCount(defaults($itemCount, $this->getItemsPerPage()));
+               $this->setPage(defaults($_GET, 'page', 1));
+       }
+
+       /**
+        * Returns the start offset for a LIMIT clause. Starts at 0.
+        *
+        * @return integer
+        */
+       public function getStart()
+       {
+               return max(0, ($this->page * $this->itemsPerPage) - $this->itemsPerPage);
+       }
+
+       /**
+        * Returns the number of items per page
+        *
+        * @return integer
+        */
+       public function getItemsPerPage()
+       {
+               return $this->itemsPerPage;
+       }
+
+       /**
+        * Returns the current page number
+        *
+        * @return type
+        */
+       public function getPage()
+       {
+               return $this->page;
+       }
+
+       /**
+        * Returns the base query string.
+        *
+        * Warning: this isn't the same value as passed to the constructor.
+        * See setQueryString for the inventory of transformations
+        *
+        * @see setBaseQuery()
+        * @return string
+        */
+       public function getBaseQueryString()
+       {
+               return $this->baseQueryString;
+       }
+
+       /**
+        * Sets the number of items per page, 1 minimum.
+        *
+        * @param integer $itemsPerPage
+        */
+       public function setItemsPerPage($itemsPerPage)
+       {
+               $this->itemsPerPage = max(1, intval($itemsPerPage));
+       }
+
+       /**
+        * Sets the current page number. Starts at 1.
+        *
+        * @param integer $page
+        */
+       public function setPage($page)
+       {
+               $this->page = max(1, intval($page));
+       }
+
+       /**
+        * Sets the item count, 0 minimum.
+        *
+        * @param integer $itemCount
+        */
+       public function setItemCount($itemCount)
+       {
+               $this->itemCount = max(0, intval($itemCount));
+       }
+
+       /**
+        * Sets the base query string from a full query string.
+        *
+        * Strips the 'page' parameter, and remove the 'q=' string for some reason.
+        *
+        * @param string $queryString
+        */
+       public function setQueryString($queryString)
+       {
+               $stripped = preg_replace('/([&?]page=[0-9]*)/', '', $queryString);
+
+               $stripped = str_replace('q=', '', $stripped);
+               $stripped = trim($stripped, '/');
+
+               $this->baseQueryString = $stripped;
+       }
+
+       /**
+        * Ensures the provided URI has its query string punctuation in order.
+        *
+        * @param string $uri
+        * @return string
+        */
+       private function ensureQueryParameter($uri)
+       {
+               if (strpos($uri, '?') === false && ($pos = strpos($uri, '&')) !== false) {
+                       $uri = substr($uri, 0, $pos) . '?' . substr($uri, $pos + 1);
+               }
+
+               return $uri;
+       }
+
+       /**
+        * @brief Minimal pager (newer/older)
+        *
+        * This mode is intended for reverse chronological pages and presents only two links, newer (previous) and older (next).
+        * The itemCount is the number of displayed items. If no items are displayed, the older button is disabled.
+        *
+        * Example usage:
+        *
+        * $pager = new Pager($a->query_string);
+        *
+        * $params = ['order' => ['sort_field' => true], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
+        * $items = DBA::toArray(DBA::select($table, $fields, $condition, $params));
+        *
+        * $html = $pager->renderMinimal(count($items));
+        *
+        * @param integer $itemCount The number of displayed items on the page
+        * @return string HTML string of the pager
+        */
+       public function renderMinimal($itemCount)
+       {
+               $this->setItemCount($itemCount);
+
+               $data = [
+                       'class' => 'pager',
+                       'prev'  => [
+                               'url'   => $this->ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() - 1)),
+                               'text'  => L10n::t('newer'),
+                               'class' => 'previous' . ($this->getPage() == 1 ? ' disabled' : '')
+                       ],
+                       'next'  => [
+                               'url'   => $this->ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() + 1)),
+                               'text'  => L10n::t('older'),
+                               'class' =>  'next' . ($this->itemCount <= 0 ? ' disabled' : '')
+                       ]
+               ];
+
+               $tpl = get_markup_template('paginate.tpl');
+               return replace_macros($tpl, ['pager' => $data]);
+       }
+
+       /**
+        * @brief Full pager (first / prev / 1 / 2 / ... / 14 / 15 / next / last)
+        *
+        * This mode presents page numbers as well as first, previous, next and last links.
+        * The itemCount is the total number of items including those not displayed.
+        *
+        * Example usage:
+        *
+        * $total = DBA::count($table, $condition);
+        *
+        * $pager = new Pager($a->query_string, $total);
+        *
+        * $params = ['limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
+        * $items = DBA::toArray(DBA::select($table, $fields, $condition, $params));
+        *
+        * $html = $pager->renderFull();
+        *
+        * @return string HTML string of the pager
+        */
+       public function renderFull()
+       {
+               $data = [];
+
+               $data['class'] = 'pagination';
+               if ($this->itemCount > $this->getItemsPerPage()) {
+                       $data['first'] = [
+                               'url'   => $this->ensureQueryParameter($this->baseQueryString . '&page=1'),
+                               'text'  => L10n::t('first'),
+                               'class' => $this->getPage() == 1 ? 'disabled' : ''
+                       ];
+                       $data['prev'] = [
+                               'url'   => $this->ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() - 1)),
+                               'text'  => L10n::t('prev'),
+                               'class' => $this->getPage() == 1 ? 'disabled' : ''
+                       ];
+
+                       $numpages = $this->itemCount / $this->getItemsPerPage();
+
+                       $numstart = 1;
+                       $numstop = $numpages;
+
+                       // Limit the number of displayed page number buttons.
+                       if ($numpages > 8) {
+                               $numstart = (($this->getPage() > 4) ? ($this->getPage() - 4) : 1);
+                               $numstop = (($this->getPage() > ($numpages - 7)) ? $numpages : ($numstart + 8));
+                       }
+
+                       $pages = [];
+
+                       for ($i = $numstart; $i <= $numstop; $i++) {
+                               if ($i == $this->getPage()) {
+                                       $pages[$i] = [
+                                               'url'   => '#',
+                                               'text'  => $i,
+                                               'class' => 'current active'
+                                       ];
+                               } else {
+                                       $pages[$i] = [
+                                               'url'   => $this->ensureQueryParameter($this->baseQueryString . '&page=' . $i),
+                                               'text'  => $i,
+                                               'class' => 'n'
+                                       ];
+                               }
+                       }
+
+                       if (($this->itemCount % $this->getItemsPerPage()) != 0) {
+                               if ($i == $this->getPage()) {
+                                       $pages[$i] = [
+                                               'url'   => '#',
+                                               'text'  => $i,
+                                               'class' => 'current active'
+                                       ];
+                               } else {
+                                       $pages[$i] = [
+                                               'url'   => $this->ensureQueryParameter($this->baseQueryString . '&page=' . $i),
+                                               'text'  => $i,
+                                               'class' => 'n'
+                                       ];
+                               }
+                       }
+
+                       $data['pages'] = $pages;
+
+                       $lastpage = (($numpages > intval($numpages)) ? intval($numpages)+1 : $numpages);
+
+                       $data['next'] = [
+                               'url'   => $this->ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() + 1)),
+                               'text'  => L10n::t('next'),
+                               'class' => $this->getPage() == $lastpage ? 'disabled' : ''
+                       ];
+                       $data['last'] = [
+                               'url'   => $this->ensureQueryParameter($this->baseQueryString . '&page=' . $lastpage),
+                               'text'  => L10n::t('last'),
+                               'class' => $this->getPage() == $lastpage ? 'disabled' : ''
+                       ];
+               }
+
+               $tpl = get_markup_template('paginate.tpl');
+               return replace_macros($tpl, ['pager' => $data]);
+       }
+}