Skip to content

Commit

Permalink
[FEATURE] Add pagination to routes (#36)
Browse files Browse the repository at this point in the history
Releases: master, 9.1, 9.0
  • Loading branch information
benjaminkott authored Feb 14, 2019
1 parent 2fe9b8c commit a055325
Show file tree
Hide file tree
Showing 16 changed files with 257 additions and 20 deletions.
10 changes: 7 additions & 3 deletions Classes/Controller/PostController.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,12 @@ public function injectBlogCacheService(CacheService $cacheService): void

/**
* @param ViewInterface $view
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException
*/
protected function initializeView(ViewInterface $view): void
{
parent::initializeView($view);
if ($this->request->hasArgument('format') && $this->request->getArgument('format') === 'rss') {
$action = '.' . $this->request->getArgument('action');
if ($this->request->getFormat() === 'rss') {
$action = '.' . $this->request->getControllerActionName();

This comment has been minimized.

Copy link
@mbrodala

mbrodala Apr 23, 2019

Contributor

This should have been done in a separate change as a bugfix and backported to v8 IMO. I just found this bug on a v8 instance and fixed it manually only before discovering this drive-by change.

I've just added #54 for the v8 bugfix.

$arguments = [];
switch ($action) {
case '.listPostsByCategory':
Expand All @@ -121,6 +120,11 @@ protected function initializeView(ViewInterface $view): void
$arguments[] = $this->arguments['tag']->getValue()->getTitle();
}
break;
case '.listPostsByAuthor':
if (isset($this->arguments['author'])) {
$arguments[] = $this->arguments['author']->getValue()->getName();
}
break;
default:
}
$feedData = [
Expand Down
143 changes: 143 additions & 0 deletions Classes/Routing/Aspect/StaticDatabaseMapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php
declare(strict_types = 1);

namespace T3G\AgencyPack\Blog\Routing\Aspect;

use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Routing\Aspect\StaticMappableAspectInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class StaticDatabaseMapper implements StaticMappableAspectInterface, \Countable
{
/**
* @var array
*/
protected $settings;

/**
* @var string
*/
protected $field;

/**
* @var string
*/
protected $table;

/**
* @var string
*/
protected $groupBy;

/**
* @var array
*/
protected $where;

/**
* @var array
*/
protected $values;

/**
* @param array $settings
* @throws \InvalidArgumentException
*/
public function __construct(array $settings)
{
$field = $settings['field'] ?? null;
$table = $settings['table'] ?? null;
$where = $settings['where'] ?? [];
$groupBy = $settings['groupBy'] ?? '';

if (!is_string($field)) {
throw new \InvalidArgumentException('field must be string', 1550156808);
}
if (!is_string($table)) {
throw new \InvalidArgumentException('table must be string', 1550156812);
}
if (!is_string($groupBy)) {
throw new \InvalidArgumentException('groupBy must be string', 1550158149);
}
if (!is_array($where)) {
throw new \InvalidArgumentException('where must be an array', 1550157442);
}

$this->settings = $settings;
$this->field = $field;
$this->table = $table;
$this->where = $where;
$this->groupBy = $groupBy;
$this->values = $this->buildValues();
}

/**
* {@inheritdoc}
*/
public function count(): int
{
return count($this->values);
}

/**
* {@inheritdoc}
*/
public function generate(string $value): ?string
{
return $this->respondWhenInValues($value);
}

/**
* {@inheritdoc}
*/
public function resolve(string $value): ?string
{
return $this->respondWhenInValues($value);
}

/**
* @param string $value
* @return string|null
*/
protected function respondWhenInValues(string $value): ?string
{
if (in_array($value, $this->values, true)) {
return $value;
}
return null;
}

/**
* Builds range based on given settings and ensures each item is string.
* The amount of items is limited to 1000 in order to avoid brute-force
* scenarios and the risk of cache-flooding.
*
* In case that is not enough, creating a custom and more specific mapper
* is encouraged. Using high values that are not distinct exposes the site
* to the risk of cache-flooding.
*
* @return string[]
* @throws \LengthException
*/
protected function buildValues(): array
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($this->table);

$queryBuilder
->select($this->field)
->from($this->table);

if ($this->groupBy !== '') {
$queryBuilder->groupBy($this->groupBy);
}

if (!empty($this->where)) {
foreach ($this->where as $key => $value) {
$queryBuilder->andWhere($key, $queryBuilder->createNamedParameter($value));
}
}

return array_map('strval', array_column($queryBuilder->execute()->fetchAll(), $this->field));
}
}
1 change: 0 additions & 1 deletion Classes/ViewHelpers/Link/ArchiveViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public function render(): string
->setUseCacheHash(true);
if ($rssFormat) {
$uriBuilder
->setFormat('rss')
->setTargetPageType($this->getTypoScriptFrontendController()->tmpl->setup['blog_rss_archive.']['typeNum']);
}
$uri = $uriBuilder->uriFor('listPostsByDate', $arguments, 'Post', 'Blog', 'Archive');
Expand Down
1 change: 0 additions & 1 deletion Classes/ViewHelpers/Link/AuthorViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ protected function getUriBuilder(int $pageUid, array $additionalParams, bool $rs
->setArguments($additionalParams);
if ($rssFormat) {
$uriBuilder
->setFormat('rss')
->setTargetPageType($this->getTypoScriptFrontendController()->tmpl->setup['blog_rss_author.']['typeNum']);
}

Expand Down
1 change: 0 additions & 1 deletion Classes/ViewHelpers/Link/CategoryViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ public function render(): string
->setUseCacheHash(true);
if ($rssFormat) {
$uriBuilder
->setFormat('rss')
->setTargetPageType($this->getTypoScriptFrontendController()->tmpl->setup['blog_rss_category.']['typeNum']);
}
$uri = $uriBuilder->uriFor('listPostsByCategory', $arguments, 'Post', 'Blog', 'Category');
Expand Down
1 change: 0 additions & 1 deletion Classes/ViewHelpers/Link/TagViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ public function render(): string
->setUseCacheHash(true);
if ($rssFormat) {
$uriBuilder
->setFormat('rss')
->setTargetPageType($this->getTypoScriptFrontendController()->tmpl->setup['blog_rss_tag.']['typeNum']);
}
$uri = $uriBuilder->uriFor('listPostsByTag', $arguments, 'Post', 'Blog', 'Tag');
Expand Down
37 changes: 29 additions & 8 deletions Configuration/Routes/BlogArchive.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,42 @@ routeEnhancers:
plugin: Archive
routes:
-
routePath: '/{year}'
routePath: '/archive/{year}'
_controller: 'Post::listPostsByDate'
_arguments:
year: year
-
routePath: '/{year}/{month}'
routePath: '/archive/{year}/page-{page}'
_controller: 'Post::listPostsByDate'
_arguments:
year: year
page: '@widget_0/currentPage'
-
routePath: '/archive/{year}/{month}'
_controller: 'Post::listPostsByDate'
_arguments:
year: year
month: month
-
routePath: '/archive/{year}/{month}/page-{page}'
_controller: 'Post::listPostsByDate'
_arguments:
year: year
month: month
page: '@widget_0/currentPage'
defaultController: 'Post::listPostsByDate'
defaults:
year: ''
month: ''
requirements:
year: '[0-9]{1..4}'
month: '[a-z]+'
page: '\d+'
aspects:
year:
type: StaticRangeMapper
start: '1950'
end: '2050'
type: BlogStaticDatabaseMapper
table: 'pages'
field: 'crdate_year'
groupBy: 'crdate_year'
where:
doktype: 137
month:
type: StaticValueMapper
map:
Expand Down Expand Up @@ -70,3 +87,7 @@ routeEnhancers:
octobre: 10
novembre: 11
decembre: 12
page:
type: StaticRangeMapper
start: '1'
end: '99'
13 changes: 12 additions & 1 deletion Configuration/Routes/BlogAuthorPosts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,28 @@ routeEnhancers:
plugin: AuthorPosts
routes:
-
routePath: '/{author_title}'
routePath: '/author/{author_title}'
_controller: 'Post::listPostsByAuthor'
_arguments:
author_title: author
-
routePath: '/author/{author_title}/page-{page}'
_controller: 'Post::listPostsByAuthor'
_arguments:
author_title: author
page: '@widget_0/currentPage'
defaultController: 'Post::listPostsByAuthor'
requirements:
author_title: '^[a-z0-9].*$'
page: '\d+'
aspects:
author_title:
type: PersistedPatternMapper
tableName: 'tx_blog_domain_model_author'
routeFieldPattern: '^(?P<slug>.+)$'
routeFieldName: 'slug'
routeFieldResult: '{slug}'
page:
type: StaticRangeMapper
start: '1'
end: '99'
15 changes: 14 additions & 1 deletion Configuration/Routes/BlogCategory.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,28 @@ routeEnhancers:
plugin: Category
routes:
-
routePath: '/{category_title}'
routePath: '/category/{category_title}'
_controller: 'Post::listPostsByCategory'
_arguments:
category_title: category
-
routePath: '/category/{category_title}/page-{page}'
_controller: 'Post::listPostsByCategory'
_arguments:
category_title: category
page: '@widget_0/currentPage'
defaultController: 'Post::listPostsByCategory'
requirements:
category_title: '^[a-z0-9].*$'
page: '\d+'
aspects:
category_title:
type: PersistedPatternMapper
tableName: sys_category
routeFieldPattern: '^(?P<slug>.+)$'
routeFieldName: 'slug'
routeFieldResult: '{slug}'
page:
type: StaticRangeMapper
start: '1'
end: '99'
19 changes: 19 additions & 0 deletions Configuration/Routes/BlogPosts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
routeEnhancers:
BlogPosts:
type: Extbase
extension: Blog
plugin: Posts
routes:
-
routePath: '/page-{page}'
_controller: 'Post::listRecentPosts'
_arguments:
page: '@widget_0/currentPage'
defaultController: 'Post::listRecentPosts'
requirements:
page: '\d+'
aspects:
page:
type: StaticRangeMapper
start: '1'
end: '99'
15 changes: 14 additions & 1 deletion Configuration/Routes/BlogTag.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,28 @@ routeEnhancers:
plugin: Tag
routes:
-
routePath: '/{tag_title}'
routePath: '/tag/{tag_title}'
_controller: 'Post::listPostsByTag'
_arguments:
tag_title: tag
-
routePath: '/tag/{tag_title}/page-{page}'
_controller: 'Post::listPostsByTag'
_arguments:
tag_title: tag
page: '@widget_0/currentPage'
defaultController: 'Post::listPostsByTag'
requirements:
tag_title: '^[a-z0-9].*$'
page: '\d+'
aspects:
tag_title:
type: PersistedPatternMapper
tableName: tx_blog_domain_model_tag
routeFieldPattern: '^(?P<slug>.+)$'
routeFieldName: 'slug'
routeFieldResult: '{slug}'
page:
type: StaticRangeMapper
start: '1'
end: '99'
1 change: 1 addition & 0 deletions Configuration/Routes/Default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ imports:
- { resource: "EXT:blog/Configuration/Routes/BlogArchive.yaml" }
- { resource: "EXT:blog/Configuration/Routes/BlogAuthorPosts.yaml" }
- { resource: "EXT:blog/Configuration/Routes/BlogFeedWidget.yaml" }
- { resource: "EXT:blog/Configuration/Routes/BlogPosts.yaml" }
Loading

0 comments on commit a055325

Please sign in to comment.