friendica/src/Content/Pager.php

290 lines
8.0 KiB
PHP
Raw Normal View History

2018-10-24 02:07:21 -04:00
<?php
2020-02-09 09:45:36 -05:00
/**
2023-01-01 09:36:24 -05:00
* @copyright Copyright (C) 2010-2023, the Friendica project
2020-02-09 09:45:36 -05:00
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
2018-10-24 02:07:21 -04:00
namespace Friendica\Content;
2020-02-16 11:53:52 -05:00
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Util\Strings;
2018-10-24 02:07:21 -04:00
/**
* The Pager has two very different output, Minimal and Full, see renderMinimal() and renderFull() for more details.
*/
class Pager
{
2020-02-25 16:16:27 -05:00
/** @var int Default count of items per page */
const ITEMS_PER_PAGE = 50;
2020-02-16 11:53:52 -05:00
/** @var integer */
2018-10-24 02:07:21 -04:00
private $page = 1;
2020-02-16 11:53:52 -05:00
/** @var integer */
2020-02-25 16:16:27 -05:00
protected $itemsPerPage = self::ITEMS_PER_PAGE;
2020-02-16 11:53:52 -05:00
/** @var string */
2020-02-16 03:23:27 -05:00
protected $baseQueryString = '';
2018-10-24 02:07:21 -04:00
2020-02-16 11:53:52 -05:00
/** @var L10n */
protected $l10n;
2018-10-24 02:07:21 -04:00
/**
* Instantiates a new Pager with the base parameters.
*
* Guesses the page number from the GET parameter 'page'.
*
* @param L10n $l10n
* @param string $queryString The query string of the current page
* @param int $itemsPerPage An optional number of items per page to override the default value
2018-10-24 02:07:21 -04:00
*/
public function __construct(L10n $l10n, string $queryString, int $itemsPerPage = 50)
2018-10-24 02:07:21 -04:00
{
2020-02-16 11:53:52 -05:00
$this->l10n = $l10n;
2018-10-24 02:07:21 -04:00
$this->setQueryString($queryString);
$this->setItemsPerPage($itemsPerPage);
2022-08-16 07:23:47 -04:00
$this->setPage((int)($_GET['page'] ?? 0) ?: 1);
2018-10-24 02:07:21 -04:00
}
/**
* Returns the start offset for a LIMIT clause. Starts at 0.
*
* @return int
2018-10-24 02:07:21 -04:00
*/
public function getStart(): int
2018-10-24 02:07:21 -04:00
{
return max(0, ($this->page * $this->itemsPerPage) - $this->itemsPerPage);
}
/**
* Returns the number of items per page
*
* @return int
2018-10-24 02:07:21 -04:00
*/
public function getItemsPerPage(): int
2018-10-24 02:07:21 -04:00
{
return $this->itemsPerPage;
}
/**
* Returns the current page number
*
2019-01-06 16:06:53 -05:00
* @return int
2018-10-24 02:07:21 -04:00
*/
public function getPage(): int
2018-10-24 02:07:21 -04:00
{
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
2018-10-24 02:07:21 -04:00
*
* @see setBaseQuery()
* @return string
*/
public function getBaseQueryString()
{
return Strings::ensureQueryParameter($this->baseQueryString);
2018-10-24 02:07:21 -04:00
}
/**
* Sets the number of items per page, 1 minimum.
*
* @param int $itemsPerPage
2018-10-24 02:07:21 -04:00
*/
public function setItemsPerPage(int $itemsPerPage)
2018-10-24 02:07:21 -04:00
{
$this->itemsPerPage = max(1, intval($itemsPerPage));
}
/**
* Sets the current page number. Starts at 1.
*
* @param int $page
2018-10-24 02:07:21 -04:00
*/
public function setPage(int $page)
2018-10-24 02:07:21 -04:00
{
$this->page = max(1, $page);
2018-10-24 02:07:21 -04:00
}
/**
* Sets the base query string from a full query string.
*
* Strips the 'page' parameter
2018-10-24 02:07:21 -04:00
*
* @param string $queryString
*/
public function setQueryString(string $queryString)
2018-10-24 02:07:21 -04:00
{
$stripped = preg_replace('/([&?]page=[0-9]*)/', '', $queryString);
$stripped = trim($stripped, '/');
$this->baseQueryString = $stripped;
}
/**
2020-01-19 01:05:23 -05:00
* Minimal pager (newer/older)
2018-10-24 02:07:21 -04:00
*
* 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));
*
2020-02-16 03:23:27 -05:00
* @param int $itemCount The number of displayed items on the page
2018-10-24 02:07:21 -04:00
* @return string HTML string of the pager
2020-02-16 03:23:27 -05:00
* @throws \Exception
2018-10-24 02:07:21 -04:00
*/
public function renderMinimal(int $itemCount): string
2018-10-24 02:07:21 -04:00
{
$displayedItemCount = max(0, intval($itemCount));
2018-10-24 02:07:21 -04:00
$data = [
'class' => 'pager',
'prev' => [
'url' => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() - 1)),
2020-02-16 11:53:52 -05:00
'text' => $this->l10n->t('newer'),
2018-10-24 02:07:21 -04:00
'class' => 'previous' . ($this->getPage() == 1 ? ' disabled' : '')
],
'next' => [
'url' => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() + 1)),
2020-02-16 11:53:52 -05:00
'text' => $this->l10n->t('older'),
'class' => 'next' . ($displayedItemCount < $this->getItemsPerPage() ? ' disabled' : '')
2018-10-24 02:07:21 -04:00
]
];
$tpl = Renderer::getMarkupTemplate('paginate.tpl');
return Renderer::replaceMacros($tpl, ['pager' => $data]);
2018-10-24 02:07:21 -04:00
}
/**
2020-01-19 01:05:23 -05:00
* Full pager (first / prev / 1 / 2 / ... / 14 / 15 / next / last)
2018-10-24 02:07:21 -04:00
*
* 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();
*
* @param int $itemCount The total number of items including those note displayed on the page
2018-10-24 02:07:21 -04:00
* @return string HTML string of the pager
2019-01-06 16:06:53 -05:00
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
2018-10-24 02:07:21 -04:00
*/
public function renderFull(int $itemCount): string
2018-10-24 02:07:21 -04:00
{
$totalItemCount = max(0, $itemCount);
2018-10-24 02:07:21 -04:00
$data = [];
$data['class'] = 'pagination';
if ($totalItemCount > $this->getItemsPerPage()) {
2018-10-24 02:07:21 -04:00
$data['first'] = [
'url' => Strings::ensureQueryParameter($this->baseQueryString . '&page=1'),
2020-02-16 11:53:52 -05:00
'text' => $this->l10n->t('first'),
2018-10-24 02:07:21 -04:00
'class' => $this->getPage() == 1 ? 'disabled' : ''
];
$data['prev'] = [
'url' => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() - 1)),
2020-02-16 11:53:52 -05:00
'text' => $this->l10n->t('prev'),
2018-10-24 02:07:21 -04:00
'class' => $this->getPage() == 1 ? 'disabled' : ''
];
$numpages = $totalItemCount / $this->getItemsPerPage();
2018-10-24 02:07:21 -04:00
$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' => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . $i),
2018-10-24 02:07:21 -04:00
'text' => $i,
'class' => 'n'
];
}
}
if (($totalItemCount % $this->getItemsPerPage()) != 0) {
2018-10-24 02:07:21 -04:00
if ($i == $this->getPage()) {
$pages[$i] = [
'url' => '#',
'text' => $i,
'class' => 'current active'
];
} else {
$pages[$i] = [
'url' => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . $i),
2018-10-24 02:07:21 -04:00
'text' => $i,
'class' => 'n'
];
}
}
$data['pages'] = $pages;
$lastpage = (($numpages > intval($numpages)) ? intval($numpages)+1 : $numpages);
$data['next'] = [
'url' => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . ($this->getPage() + 1)),
2020-02-16 11:53:52 -05:00
'text' => $this->l10n->t('next'),
2018-10-24 02:07:21 -04:00
'class' => $this->getPage() == $lastpage ? 'disabled' : ''
];
$data['last'] = [
'url' => Strings::ensureQueryParameter($this->baseQueryString . '&page=' . $lastpage),
2020-02-16 11:53:52 -05:00
'text' => $this->l10n->t('last'),
2018-10-24 02:07:21 -04:00
'class' => $this->getPage() == $lastpage ? 'disabled' : ''
];
}
$tpl = Renderer::getMarkupTemplate('paginate.tpl');
return Renderer::replaceMacros($tpl, ['pager' => $data]);
2018-10-24 02:07:21 -04:00
}
}