Skip to content

Commit

Permalink
Introduce classes in paginator
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Richter committed Nov 26, 2024
1 parent 5dd4bbd commit a906fa6
Show file tree
Hide file tree
Showing 3 changed files with 222 additions and 69 deletions.
85 changes: 75 additions & 10 deletions Classes/Common/Paginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
class Paginator
{
const CURRENT_PAGE = 'current';
const DOTS = '...';

const SHOW_CLASS = 'show';
const HIDE_CLASS = 'hide-mobile';
const DOTS_CLASS = 'disabled';
const CURRENT_CLASS = 'current disabled';

protected int $itemsPerPage = -1;
protected int $totalItems = -1;
Expand Down Expand Up @@ -55,12 +61,14 @@ public function setExtensionConfiguration(ExtensionConfiguration $extensionConfi
$this->itemsPerPage = (int) $extConf['itemsPerPage'];
$paginationRangeString = Str::of($extConf['paginationRange']);

if($paginationRangeString->match('/([1-9][0-9]*, *)*[1-9][0-9]*/') == "") {
if(!$paginationRangeString->isMatch('/^\d* *(, *\d+)*$/')) {
throw new \Exception('Check the configuration of liszt common. The pagination range needs to be specified in the form "1,2,3..."');
}

$this->paginationRange = $paginationRangeString->explode(',')->
map(function($rangeItem) { return self::getRangeItem($rangeItem); })->
// we always want the neighboring pages of the current page
push(1)->
unique()->
sort();

Expand Down Expand Up @@ -89,38 +97,95 @@ public function getPagination(): array
$currentPage = $this->currentPage;

$pagesBefore = $this->paginationRange->
filter()->
reverse()->
map(function($page) use ($currentPage) { return self::getPageBefore($page, $currentPage); });
$pagesAfter = $this->paginationRange->
filter()->
map(function($page) use ($currentPage, $totalPages) { return self::getPageAfter($page, $currentPage, $totalPages); });

return Collection::wrap([])->
when($this->currentPage != 1, function ($collection) { return $collection->push(1); })->
when($pagesBefore->first() > 2, function ($collection) { return $collection->push('...'); })->
// we include the first page if it is not the current one
when($this->currentPage != 1,
function ($collection) { return $collection->push([ 'page' => 1, 'class' => self::SHOW_CLASS ]); }
)->
// we include the range pages before the current page (which may be empty)
concat($pagesBefore)->
push(self::CURRENT_PAGE)->
// we include the current page
push(['page' => $this->currentPage, 'class' => self::CURRENT_CLASS])->
// we include the range pages after the current page (which may be empty)
concat($pagesAfter)->
when($this->currentPage != $totalPages, function($collection) use ($totalPages) { return $collection->push($totalPages); })->
// we include the last page if it is not the current one
when($this->currentPage != $totalPages,
function($collection) use ($totalPages) { return $collection->push([ 'page' => $totalPages, 'class' => self::SHOW_CLASS ]);}
)->
// we filter out empty results from the pagesBefore or pagesAfter arrays
filter()->
// we introduce dots wherever the distance between two pages is greater than one, so we prepare by adding a dummy
push(null)->
// sliding through pairs of pages
sliding(2)->
// returning page 1 if the distance is 1 and page 1 and dots elsewise (here we need the dummy)
mapSpread( function ($page1, $page2) { return self::insertDots($page1, $page2); })->
// and flatten out everything
flatten(1)->
values()->
all();
}

private static function insertDots(?array $page1, ?array $page2): array
{
if ($page2 == null) return [ $page1 ];

if ($page2['page'] - $page1['page'] == 1) {
return [ $page1 ];
}

$dots = [ 'page' => self::DOTS, 'class' => self::DOTS_CLASS ];
return [ $page1, $dots ];
}

private static function getPageBefore(int $page, int $currentPage): ?int
private static function getPageBefore(?int $page, int $currentPage): ?array
{
$result = $currentPage - $page;
return $result > 1 ? $result : null;

if ($result < 2) return null;

if ($page == 1) {
return [
'page' => $result,
'class' => self::SHOW_CLASS
];
}

return [
'page' => $result,
'class' => self::HIDE_CLASS
];
}

private static function getPageAfter(int $page, int $currentPage, int $totalPages): ?int
private static function getPageAfter(?int $page, int $currentPage, int $totalPages): ?array
{
$result = $currentPage + $page;
return $result < $totalPages ? $result : null;

if ($result >= $totalPages) return null;

if ($page == 1) {
return [
'page' => $result,
'class' => self::SHOW_CLASS
];
}

return [
'page' => $result,
'class' => self::HIDE_CLASS
];
}

private static function getRangeItem(string $rangeItem): int
private static function getRangeItem(string $rangeItem): ?int
{
if ($rangeItem == '') return null;
return (int) trim($rangeItem);
}
}
6 changes: 5 additions & 1 deletion Resources/Private/Partials/Pagination.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
{namespace lc=Slub\LisztCommon\ViewHelpers}
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:debug>{_all}</f:debug>
<nav class="searchresults-pagination" aria-label="{f:translate(key: 'searchResults_pagination_label', extensionName: 'liszt_common')}">
<ul>
<f:for each="{pagination}" as="page">
<li>
<f:link.action action="index" controller="Search" pluginName="SearchListing" arguments="{lc:searchParams(action: 'add', searchParamsArray: searchParams, key: 'searchParamsPage', value: page.page)}" additionalAttributes="{aria-current:'true'}" class="{page.class}">
{page.page}
</f:link.action>
<f:comment><!--
<f:if condition="{page} == {currentString}">
<f:then>
<f:link.action action="index" controller="Search" pluginName="SearchListing" arguments="{lc:searchParams(action: 'add', searchParamsArray: searchParams, key: 'searchParamsPage', value: page)}" additionalAttributes="{aria-current:'true'}" class="current">
Expand All @@ -17,6 +20,7 @@
</f:link.action>
</f:else>
</f:if>
--></f:comment>
</li>
</f:for>
</ul>
Expand Down
Loading

0 comments on commit a906fa6

Please sign in to comment.