Skip to content

Commit

Permalink
[BUGFIX] Correct Pagination (#210)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminkott authored Jun 23, 2021
1 parent 8e66e97 commit ca37059
Show file tree
Hide file tree
Showing 17 changed files with 339 additions and 249 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ jobs:
- name: Info
run: composer info

- name: CGL
run: php-cs-fixer fix --dry-run --verbose

- name: Lint PHP
run: composer t3g:test:php:lint

- name: CGL
run: php-cs-fixer fix --dry-run --verbose

- name: Unit Tests without coverage
if: matrix.typo3 != '^10.4'
run: composer t3g:test:php:unit
Expand Down
44 changes: 31 additions & 13 deletions Classes/Controller/PostController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@
use T3G\AgencyPack\Blog\Domain\Repository\CategoryRepository;
use T3G\AgencyPack\Blog\Domain\Repository\PostRepository;
use T3G\AgencyPack\Blog\Domain\Repository\TagRepository;
use T3G\AgencyPack\Blog\Pagination\BlogPagination;
use T3G\AgencyPack\Blog\Service\CacheService;
use T3G\AgencyPack\Blog\Service\MetaTagService;
use T3G\AgencyPack\Blog\Utility\ArchiveUtility;
use TYPO3\CMS\Core\Http\NormalizedParams;
use TYPO3\CMS\Core\Pagination\SimplePagination;
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Extbase\Pagination\QueryResultPaginator;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;

Expand Down Expand Up @@ -156,21 +157,14 @@ protected function initializeView(ViewInterface $view): void
public function listRecentPostsAction(int $currentPage = 1): ResponseInterface
{
$maximumItems = (int) ($this->settings['lists']['posts']['maximumDisplayedItems'] ?? 0);
$itemsPerPage = (int) ($this->settings['lists']['pagination']['itemsPerPage'] ?? 10);
$posts = (0 === $maximumItems)
? $this->postRepository->findAll()
: $this->postRepository->findAllWithLimit($maximumItems);
$pagination = $this->getPagination($posts, $currentPage);

$paginator = null;
$pagination = null;
if (count($posts) > $itemsPerPage) {
$paginator = new QueryResultPaginator($posts, $currentPage, $itemsPerPage);
$pagination = new SimplePagination($paginator);
}
$this->view->assign('type', 'recent');
$this->view->assign('posts', $posts);
$this->view->assign('pagination', $pagination);
$this->view->assign('paginator', $paginator);
return $this->htmlResponse();
}

Expand All @@ -193,25 +187,28 @@ public function listLatestPostsAction(): ResponseInterface
/**
* @param int $year
* @param int $month
* @param int $currentPage
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
* @throws \Exception
*/
public function listPostsByDateAction(int $year = null, int $month = null): ResponseInterface
public function listPostsByDateAction(int $year = null, int $month = null, int $currentPage = 1): ResponseInterface
{
if ($year === null) {
$posts = $this->postRepository->findMonthsAndYearsWithPosts();
$this->view->assign('archiveData', ArchiveUtility::extractDataFromPosts($posts));
} else {
$dateTime = new \DateTimeImmutable(sprintf('%d-%d-1', $year, $month ?? 1));
$posts = $this->postRepository->findByMonthAndYear($year, $month);
$pagination = $this->getPagination($posts, $currentPage);
$this->view->assign('type', 'bydate');
$this->view->assign('month', $month);
$this->view->assign('year', $year);
$this->view->assign('timestamp', $dateTime->getTimestamp());
$this->view->assign('posts', $posts);
$this->view->assign('pagination', $pagination);
$title = str_replace([
'###MONTH###',
'###MONTH_NAME###',
Expand All @@ -231,10 +228,11 @@ public function listPostsByDateAction(int $year = null, int $month = null): Resp
* Show a list of posts by given category.
*
* @param Category|null $category
* @param int $currentPage
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
*/
public function listPostsByCategoryAction(Category $category = null): ResponseInterface
public function listPostsByCategoryAction(Category $category = null, int $currentPage = 1): ResponseInterface
{
if ($category === null) {
$categories = $this->categoryRepository->getByReference(
Expand All @@ -250,8 +248,10 @@ public function listPostsByCategoryAction(Category $category = null): ResponseIn

if ($category) {
$posts = $this->postRepository->findAllByCategory($category);
$pagination = $this->getPagination($posts, $currentPage);
$this->view->assign('type', 'bycategory');
$this->view->assign('posts', $posts);
$this->view->assign('pagination', $pagination);
$this->view->assign('category', $category);
MetaTagService::set(MetaTagService::META_TITLE, (string) $category->getTitle());
MetaTagService::set(MetaTagService::META_DESCRIPTION, (string) $category->getDescription());
Expand All @@ -265,15 +265,18 @@ public function listPostsByCategoryAction(Category $category = null): ResponseIn
* Show a list of posts by given author.
*
* @param Author|null $author
* @param int $currentPage
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
*/
public function listPostsByAuthorAction(Author $author = null): ResponseInterface
public function listPostsByAuthorAction(Author $author = null, int $currentPage = 1): ResponseInterface
{
if ($author) {
$posts = $this->postRepository->findAllByAuthor($author);
$pagination = $this->getPagination($posts, $currentPage);
$this->view->assign('type', 'byauthor');
$this->view->assign('posts', $posts);
$this->view->assign('pagination', $pagination);
$this->view->assign('author', $author);
MetaTagService::set(MetaTagService::META_TITLE, (string) $author->getName());
MetaTagService::set(MetaTagService::META_DESCRIPTION, (string) $author->getBio());
Expand All @@ -287,15 +290,18 @@ public function listPostsByAuthorAction(Author $author = null): ResponseInterfac
* Show a list of posts by given tag.
*
* @param Tag|null $tag
* @param int $currentPage
* @throws \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
*/
public function listPostsByTagAction(Tag $tag = null): ResponseInterface
public function listPostsByTagAction(Tag $tag = null, int $currentPage = 1): ResponseInterface
{
if ($tag) {
$posts = $this->postRepository->findAllByTag($tag);
$pagination = $this->getPagination($posts, $currentPage);
$this->view->assign('type', 'bytag');
$this->view->assign('posts', $posts);
$this->view->assign('pagination', $pagination);
$this->view->assign('tag', $tag);
MetaTagService::set(MetaTagService::META_TITLE, (string) $tag->getTitle());
MetaTagService::set(MetaTagService::META_DESCRIPTION, (string) $tag->getDescription());
Expand Down Expand Up @@ -427,4 +433,16 @@ private function getRequestUrl(): string
$normalizedParams = $GLOBALS['TYPO3_REQUEST']->getAttribute('normalizedParams');
return $normalizedParams->getRequestUrl();
}

protected function getPagination(QueryResultInterface $objects, int $currentPage = 1): ?BlogPagination
{
$maximumNumberOfLinks = (int) ($this->settings['lists']['pagination']['maximumNumberOfLinks'] ?? 0);
$itemsPerPage = 10;
if ($this->request->getFormat() === 'html') {
$itemsPerPage = (int) ($this->settings['lists']['pagination']['itemsPerPage'] ?? 10);
}

$paginator = new QueryResultPaginator($objects, $currentPage, $itemsPerPage);
return new BlogPagination($paginator, $maximumNumberOfLinks);
}
}
192 changes: 192 additions & 0 deletions Classes/Pagination/BlogPagination.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
<?php
declare(strict_types = 1);

/*
* This file is part of the package t3g/blog.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/

namespace T3G\AgencyPack\Blog\Pagination;

use TYPO3\CMS\Core\Pagination\PaginationInterface;
use TYPO3\CMS\Core\Pagination\PaginatorInterface;

final class BlogPagination implements PaginationInterface
{
/**
* @var int
*/
protected $maximumNumberOfLinks = 10;

/**
* @var int
*/
protected $displayRangeStart = 0;

/**
* @var int
*/
protected $displayRangeEnd = 0;

/**
* @var PaginatorInterface
*/
protected $paginator;

public function __construct(PaginatorInterface $paginator, int $maximumNumberOfLinks = 10)
{
$this->paginator = $paginator;
$this->maximumNumberOfLinks = $maximumNumberOfLinks > 0 ? $maximumNumberOfLinks : 1;
$this->displayRangeStart = $this->getFirstPageNumber();
$this->displayRangeEnd = $this->getLastPageNumber();

$this->generateDisplayRange();
}

protected function generateDisplayRange(): void
{
$currentPageNumber = $this->getCurrentPageNumber();
$maximumNumberOfLinks = $this->getMaximumNumberOfLinks();
$delta = (int) floor($maximumNumberOfLinks / 2);
if ($this->getNumberOfPages() > $maximumNumberOfLinks) {
$this->displayRangeStart = $currentPageNumber - $delta;
$this->displayRangeEnd = $this->displayRangeStart + $maximumNumberOfLinks - 1;
while ($this->displayRangeStart < $this->getFirstPageNumber()) {
$this->displayRangeStart++;
$this->displayRangeEnd++;
}
while ($this->displayRangeEnd > $this->getLastPageNumber()) {
$this->displayRangeStart--;
$this->displayRangeEnd--;
}
}
}

public function getPreviousPageNumber(): ?int
{
$previousPage = $this->paginator->getCurrentPageNumber() - 1;

if ($previousPage > $this->paginator->getNumberOfPages()) {
return null;
}

return $previousPage >= $this->getFirstPageNumber()
? $previousPage
: null;
}

public function getCurrentPageNumber(): int
{
return $this->paginator->getCurrentPageNumber() ?? 1;
}

public function getNextPageNumber(): ?int
{
$nextPage = $this->paginator->getCurrentPageNumber() + 1;

return $nextPage <= $this->paginator->getNumberOfPages()
? $nextPage
: null;
}

public function getFirstPageNumber(): int
{
return 1;
}

public function getLastPageNumber(): int
{
return $this->paginator->getNumberOfPages();
}

public function getStartRecordNumber(): int
{
if ($this->paginator->getCurrentPageNumber() > $this->paginator->getNumberOfPages()) {
return 0;
}

return $this->paginator->getKeyOfFirstPaginatedItem() + 1;
}

public function getEndRecordNumber(): int
{
if ($this->paginator->getCurrentPageNumber() > $this->paginator->getNumberOfPages()) {
return 0;
}

return $this->paginator->getKeyOfLastPaginatedItem() + 1;
}

public function getNumberOfPages(): int
{
return $this->paginator->getNumberOfPages();
}

/**
* @return int[]
*/
public function getAllPageNumbers(): array
{
return range($this->getFirstPageNumber(), $this->getLastPageNumber());
}

/**
* @return int
*/
public function getDisplayRangeStart(): int
{
return $this->displayRangeStart;
}

/**
* @return int
*/
public function getDisplayRangeEnd(): int
{
return $this->displayRangeEnd;
}

/**
* @return int[]
*/
public function getDisplayPageNumbers(): array
{
return range($this->getDisplayRangeStart(), $this->getDisplayRangeEnd());
}

public function hasLessPages(): bool
{
return $this->getDisplayRangeStart() > $this->getFirstPageNumber();
}

public function hasMorePages(): bool
{
return $this->getDisplayRangeEnd() < $this->getLastPageNumber();
}

/**
* @return int
*/
public function getMaximumNumberOfLinks(): int
{
return $this->maximumNumberOfLinks;
}

/**
* @return PaginatorInterface
*/
public function getPaginator(): PaginatorInterface
{
return $this->paginator;
}

/**
* @return iterable
*/
public function getPaginatedItems(): iterable
{
return $this->paginator->getPaginatedItems();
}
}
4 changes: 2 additions & 2 deletions Configuration/Routes/BlogArchive.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ routeEnhancers:
_controller: 'Post::listPostsByDate'
_arguments:
year: year
page: '@widget_0/currentPage'
page: 'currentPage'
-
routePath: '/archive/{year}/{month}'
_controller: 'Post::listPostsByDate'
Expand All @@ -27,7 +27,7 @@ routeEnhancers:
_arguments:
year: year
month: month
page: '@widget_0/currentPage'
page: 'currentPage'
defaultController: 'Post::listPostsByDate'
requirements:
year: '[0-9]{1,4}'
Expand Down
2 changes: 1 addition & 1 deletion Configuration/Routes/BlogAuthorPosts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ routeEnhancers:
_controller: 'Post::listPostsByAuthor'
_arguments:
author_title: author
page: '@widget_0/currentPage'
page: 'currentPage'
defaultController: 'Post::listPostsByAuthor'
requirements:
author_title: '^[a-z0-9].*$'
Expand Down
2 changes: 1 addition & 1 deletion Configuration/Routes/BlogCategory.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ routeEnhancers:
_controller: 'Post::listPostsByCategory'
_arguments:
category_title: category
page: '@widget_0/currentPage'
page: 'currentPage'
defaultController: 'Post::listPostsByCategory'
requirements:
category_title: '^[a-z0-9].*$'
Expand Down
Loading

0 comments on commit ca37059

Please sign in to comment.