Finally migrate RSS Feed
Misusing the sitemap implementation was a bad idea and broke for every major update. I now finally migrate to custom implementation which should remove the issues for future.
This commit is contained in:
parent
02493e9540
commit
8bcdec5d94
7 changed files with 197 additions and 386 deletions
148
Classes/Frontend/RssFeed/BlogPostsDataProvider.php
Normal file
148
Classes/Frontend/RssFeed/BlogPostsDataProvider.php
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Daniel Siepmann <coding@daniel-siepmann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace DanielSiepmann\DsSite\Frontend\RssFeed;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
||||||
|
use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;
|
||||||
|
use TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor;
|
||||||
|
|
||||||
|
final class BlogPostsDataProvider implements DataProcessorInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly DatabaseQueryProcessor $databaseQueryProcessor,
|
||||||
|
private readonly ConnectionPool $connectionPool
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process(
|
||||||
|
ContentObjectRenderer $contentObjectRenderer,
|
||||||
|
array $contentObjectConfiguration,
|
||||||
|
array $processorConfiguration,
|
||||||
|
array $processedData
|
||||||
|
) {
|
||||||
|
$processedData = $this->databaseQueryProcessor->process(
|
||||||
|
$contentObjectRenderer,
|
||||||
|
$contentObjectConfiguration,
|
||||||
|
array_merge($processorConfiguration, [
|
||||||
|
'where' => 'AND no_index = 0' . $this->getAdditionalWhere($contentObjectRenderer->getRequest()),
|
||||||
|
]),
|
||||||
|
$processedData
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($processedData['pages'] as &$page) {
|
||||||
|
$page['description'] = $page['data']['abstract']
|
||||||
|
. $this->getContent(
|
||||||
|
$contentObjectRenderer,
|
||||||
|
$page['data']['uid']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $processedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getAdditionalWhere(ServerRequestInterface $request): string
|
||||||
|
{
|
||||||
|
$categoryUid = intval($request->getQueryParams()['category_uid'] ?? 0);
|
||||||
|
if ($categoryUid === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$pageUids = $this->getPageUidsWithRelationToCategory($categoryUid);
|
||||||
|
$where = $this->createAdditionalWhereForPageUids($pageUids);
|
||||||
|
|
||||||
|
if ($where !== '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return ' ' . $where;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPageUidsWithRelationToCategory(int $categoryUid): array
|
||||||
|
{
|
||||||
|
$queryBuilder = $this->connectionPool->getQueryBuilderForTable('pages');
|
||||||
|
|
||||||
|
$queryBuilder->select('uid');
|
||||||
|
$queryBuilder->from('pages');
|
||||||
|
$queryBuilder->leftJoin(
|
||||||
|
'pages',
|
||||||
|
'sys_category_record_mm',
|
||||||
|
'mm',
|
||||||
|
'pages.uid = mm.uid_foreign'
|
||||||
|
);
|
||||||
|
$queryBuilder->where(
|
||||||
|
$queryBuilder->expr()->eq(
|
||||||
|
'mm.tablenames',
|
||||||
|
$queryBuilder->createNamedParameter('pages')
|
||||||
|
),
|
||||||
|
$queryBuilder->expr()->eq(
|
||||||
|
'mm.fieldname',
|
||||||
|
$queryBuilder->createNamedParameter('categories')
|
||||||
|
),
|
||||||
|
$queryBuilder->expr()->in(
|
||||||
|
'mm.uid_local',
|
||||||
|
$queryBuilder->createNamedParameter($categoryUid)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return array_map(function (array $row) {
|
||||||
|
if (is_numeric($row['uid'])) {
|
||||||
|
return (int) $row['uid'];
|
||||||
|
}
|
||||||
|
throw new Exception('UID was not numeric: ' . var_export($row['uid'], true), 1707325559);
|
||||||
|
}, $queryBuilder->executeQuery()->fetchAllAssociative());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createAdditionalWhereForPageUids(array $pageUids): string
|
||||||
|
{
|
||||||
|
return ' AND uid IN(' . implode(',', $pageUids) . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getContent(
|
||||||
|
ContentObjectRenderer $contentObjectRenderer,
|
||||||
|
int $pageUid
|
||||||
|
): string {
|
||||||
|
$colPositions = [
|
||||||
|
50,
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
];
|
||||||
|
|
||||||
|
$content = '';
|
||||||
|
foreach ($colPositions as $colPos) {
|
||||||
|
$content .= $contentObjectRenderer->cObjGetSingle('CONTENT', [
|
||||||
|
'table' => 'tt_content',
|
||||||
|
'select.' => [
|
||||||
|
'orderBy' => 'sorting',
|
||||||
|
'where' => '{#colPos}=' . $colPos,
|
||||||
|
'pidInList' => $pageUid,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,64 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2023 Daniel Siepmann <coding@daniel-siepmann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DanielSiepmann\DsSite\Frontend\RssFeed;
|
|
||||||
|
|
||||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
|
||||||
|
|
||||||
class ContentRendering
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private readonly ContentObjectRenderer $contentObjectRenderer
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function extend(array $row): array
|
|
||||||
{
|
|
||||||
$row['description'] = $row['data']['abstract'] . $this->getContent($row['data']['uid']);
|
|
||||||
return $row;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getContent(int $pageUid): string
|
|
||||||
{
|
|
||||||
$colPositions = [
|
|
||||||
50,
|
|
||||||
0,
|
|
||||||
100,
|
|
||||||
200,
|
|
||||||
];
|
|
||||||
|
|
||||||
$content = '';
|
|
||||||
foreach ($colPositions as $colPos) {
|
|
||||||
$content .= $this->contentObjectRenderer->cObjGetSingle('CONTENT', [
|
|
||||||
'table' => 'tt_content',
|
|
||||||
'select.' => [
|
|
||||||
'orderBy' => 'sorting',
|
|
||||||
'where' => '{#colPos}=' . $colPos,
|
|
||||||
'pidInList' => $pageUid,
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $content;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 Daniel Siepmann <coding@daniel-siepmann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DanielSiepmann\DsSite\Frontend\RssFeed;
|
|
||||||
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use TYPO3\CMS\Core\Database\Connection;
|
|
||||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
|
||||||
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
||||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
|
||||||
use TYPO3\CMS\Seo\XmlSitemap\RecordsXmlSitemapDataProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides dynamic for additionalWhere,
|
|
||||||
* to only list pages for current requested category.
|
|
||||||
*/
|
|
||||||
class SitemapDataProvider extends RecordsXmlSitemapDataProvider
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
ServerRequestInterface $request,
|
|
||||||
string $key,
|
|
||||||
array $config = [],
|
|
||||||
ContentObjectRenderer $cObj = null
|
|
||||||
) {
|
|
||||||
$categoryUid = intval($request->getQueryParams()['category_uid'] ?? 0);
|
|
||||||
if ($categoryUid > 0) {
|
|
||||||
$pageUids = $this->getPageUidsWithRelationToCategory($categoryUid);
|
|
||||||
$config['additionalWhere'] = ($config['additionalWhere'] ?? '')
|
|
||||||
. $this->createAdditionalWhereForPageUids($pageUids)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::__construct($request, $key, $config, $cObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generateItems(): void
|
|
||||||
{
|
|
||||||
parent::generateItems();
|
|
||||||
|
|
||||||
$contentRendering = new ContentRendering($this->cObj);
|
|
||||||
foreach ($this->items as $key => $item) {
|
|
||||||
$this->items[$key] = $contentRendering->extend($item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getPageUidsWithRelationToCategory(int $categoryUid): array
|
|
||||||
{
|
|
||||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
|
||||||
->getQueryBuilderForTable('pages');
|
|
||||||
/* @var QueryBuilder $queryBuilder */
|
|
||||||
|
|
||||||
$queryBuilder->select('uid');
|
|
||||||
$queryBuilder->from('pages');
|
|
||||||
$queryBuilder->leftJoin(
|
|
||||||
'pages',
|
|
||||||
'sys_category_record_mm',
|
|
||||||
'mm',
|
|
||||||
'pages.uid = mm.uid_foreign'
|
|
||||||
);
|
|
||||||
$queryBuilder->where(
|
|
||||||
$queryBuilder->expr()->eq(
|
|
||||||
'mm.tablenames',
|
|
||||||
$queryBuilder->createNamedParameter('pages')
|
|
||||||
),
|
|
||||||
$queryBuilder->expr()->eq(
|
|
||||||
'mm.fieldname',
|
|
||||||
$queryBuilder->createNamedParameter('categories')
|
|
||||||
),
|
|
||||||
$queryBuilder->expr()->in(
|
|
||||||
'mm.uid_local',
|
|
||||||
$queryBuilder->createNamedParameter($categoryUid)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return array_map(function (array $row) {
|
|
||||||
return (int) $row['uid'];
|
|
||||||
}, $queryBuilder->executeQuery()->fetchAllAssociative());
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createAdditionalWhereForPageUids(array $pageUids): string
|
|
||||||
{
|
|
||||||
return ' AND uid IN(' . implode(',', $pageUids) . ')';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,167 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 Daniel Siepmann <coding@daniel-siepmann.de>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace DanielSiepmann\DsSite\Frontend\RssFeed;
|
|
||||||
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use TYPO3Fluid\Fluid\View\TemplateView;
|
|
||||||
use TYPO3\CMS\Core\Http\PropagateResponseException;
|
|
||||||
use TYPO3\CMS\Core\TypoScript\TypoScriptService;
|
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
||||||
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContextFactory;
|
|
||||||
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
|
||||||
use TYPO3\CMS\Frontend\Controller\ErrorController;
|
|
||||||
use TYPO3\CMS\Seo\XmlSitemap\Exception\InvalidConfigurationException;
|
|
||||||
use TYPO3\CMS\Seo\XmlSitemap\XmlSitemapDataProviderInterface;
|
|
||||||
|
|
||||||
class XmlSitemapRenderer
|
|
||||||
{
|
|
||||||
private array $typoScriptConfiguration = [];
|
|
||||||
|
|
||||||
protected array $configuration;
|
|
||||||
|
|
||||||
private ContentObjectRenderer $contentObjectRenderer;
|
|
||||||
|
|
||||||
protected TemplateView $view;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
protected TypoScriptService $typoScriptService,
|
|
||||||
protected RenderingContextFactory $renderingContextFactory,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setContentObjectRenderer(ContentObjectRenderer $contentObjectRenderer): void
|
|
||||||
{
|
|
||||||
$this->contentObjectRenderer = $contentObjectRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function initialize(array $fullConfiguration): void
|
|
||||||
{
|
|
||||||
$this->configuration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($fullConfiguration['plugin.']['tx_seo.'] ?? []);
|
|
||||||
$renderingContext = $this->renderingContextFactory->create();
|
|
||||||
$templatePaths = $renderingContext->getTemplatePaths();
|
|
||||||
$templatePaths->setTemplateRootPaths($this->configuration['view']['templateRootPaths']);
|
|
||||||
$templatePaths->setLayoutRootPaths($this->configuration['view']['layoutRootPaths']);
|
|
||||||
$templatePaths->setPartialRootPaths($this->configuration['view']['partialRootPaths']);
|
|
||||||
$templatePaths->setFormat('xml');
|
|
||||||
$this->view = GeneralUtility::makeInstance(TemplateView::class, $renderingContext);
|
|
||||||
$this->view->assign('settings', $this->getSettings());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render(string $_, array $typoScriptConfiguration, ServerRequestInterface $request): string
|
|
||||||
{
|
|
||||||
$this->typoScriptConfiguration = $typoScriptConfiguration;
|
|
||||||
|
|
||||||
$this->initialize($GLOBALS['TSFE']->tmpl->setup);
|
|
||||||
$this->view->assign('type', $request->getAttribute('routing')?->getPageType() ?? 0);
|
|
||||||
$sitemapType = $typoScriptConfiguration['sitemapType'] ?? 'xmlSitemap';
|
|
||||||
if (!empty($sitemap = ($request->getQueryParams()['sitemap'] ?? null))) {
|
|
||||||
return $this->renderSitemap($request, $sitemap, $sitemapType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->renderIndex($request, $sitemapType);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function renderIndex(ServerRequestInterface $request, string $sitemapType): string
|
|
||||||
{
|
|
||||||
$sitemaps = [];
|
|
||||||
foreach ($this->configuration['config'][$sitemapType]['sitemaps'] ?? [] as $sitemap => $config) {
|
|
||||||
if (!empty($config['provider']) && is_string($config['provider'])
|
|
||||||
&& class_exists($config['provider'])
|
|
||||||
&& is_subclass_of($config['provider'], XmlSitemapDataProviderInterface::class)
|
|
||||||
) {
|
|
||||||
/** @var XmlSitemapDataProviderInterface $provider */
|
|
||||||
$provider = GeneralUtility::makeInstance(
|
|
||||||
$config['provider'],
|
|
||||||
$request,
|
|
||||||
$sitemap,
|
|
||||||
(array)($config['config'] ?? [])
|
|
||||||
);
|
|
||||||
|
|
||||||
$pages = $provider->getNumberOfPages();
|
|
||||||
|
|
||||||
for ($page = 0; $page < $pages; $page++) {
|
|
||||||
$sitemaps[] = [
|
|
||||||
'key' => $sitemap,
|
|
||||||
'page' => $page,
|
|
||||||
'lastMod' => $provider->getLastModified(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->view->assign('sitemapType', $sitemapType);
|
|
||||||
$this->view->assign('sitemaps', $sitemaps);
|
|
||||||
|
|
||||||
return $this->view->render('Index');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function renderSitemap(ServerRequestInterface $request, string $sitemap, string $sitemapType): string
|
|
||||||
{
|
|
||||||
if (!empty($sitemapConfig = $this->configuration['config'][$sitemapType]['sitemaps'][$sitemap] ?? null)) {
|
|
||||||
if (class_exists($sitemapConfig['provider']) &&
|
|
||||||
is_subclass_of($sitemapConfig['provider'], XmlSitemapDataProviderInterface::class)) {
|
|
||||||
/** @var XmlSitemapDataProviderInterface $provider */
|
|
||||||
$provider = GeneralUtility::makeInstance(
|
|
||||||
$sitemapConfig['provider'],
|
|
||||||
$request,
|
|
||||||
$sitemap,
|
|
||||||
(array)($sitemapConfig['config'] ?? [])
|
|
||||||
);
|
|
||||||
|
|
||||||
$items = $provider->getItems();
|
|
||||||
|
|
||||||
$this->view->assign('items', $items);
|
|
||||||
$this->view->assign('sitemapType', $sitemapType);
|
|
||||||
|
|
||||||
$template = ($sitemapConfig['config']['template'] ?? false) ?: 'Sitemap';
|
|
||||||
return $this->view->render($template);
|
|
||||||
}
|
|
||||||
throw new InvalidConfigurationException('No valid provider set for ' . $sitemap, 1535578522);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new PropagateResponseException(
|
|
||||||
GeneralUtility::makeInstance(ErrorController::class)->pageNotFoundAction(
|
|
||||||
$request,
|
|
||||||
'No valid configuration found for sitemap ' . $sitemap
|
|
||||||
),
|
|
||||||
1535578569
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getSettings(): array
|
|
||||||
{
|
|
||||||
$settings = [];
|
|
||||||
foreach (array_keys($this->typoScriptConfiguration['userFunc.']['variables.'] ?? []) as $variableName) {
|
|
||||||
if (!is_string($variableName) || substr($variableName, -1) === '.') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$settings[$variableName] = $this->contentObjectRenderer->cObjGetSingle(
|
|
||||||
$this->typoScriptConfiguration['userFunc.']['variables.'][$variableName] ?? '',
|
|
||||||
$this->typoScriptConfiguration['userFunc.']['variables.'][$variableName . '.'] ?? []
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $settings;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,7 +18,7 @@ services:
|
||||||
arguments:
|
arguments:
|
||||||
- 'pages'
|
- 'pages'
|
||||||
|
|
||||||
DanielSiepmann\DsSite\Frontend\RssFeed\XmlSitemapRenderer:
|
DanielSiepmann\DsSite\Frontend\RssFeed\BlogPostsDataProvider:
|
||||||
public: true
|
public: true
|
||||||
|
|
||||||
DanielSiepmann\DsSite\Backend\PreviewRenderer\Video:
|
DanielSiepmann\DsSite\Backend\PreviewRenderer\Video:
|
||||||
|
|
|
@ -1,30 +1,3 @@
|
||||||
plugin.tx_seo {
|
|
||||||
view {
|
|
||||||
templateRootPaths {
|
|
||||||
20 = EXT:ds_site/Resources/Private/Templates/Sitemaps/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config {
|
|
||||||
xmlSitemap {
|
|
||||||
sitemaps {
|
|
||||||
blog-posts {
|
|
||||||
provider = DanielSiepmann\DsSite\Frontend\RssFeed\SitemapDataProvider
|
|
||||||
config {
|
|
||||||
table = pages
|
|
||||||
sortField = lastUpdated
|
|
||||||
sortOrder = DESC
|
|
||||||
lastModifiedField = tstamp
|
|
||||||
additionalWhere = AND no_index = 0
|
|
||||||
pid = {$pageUids.blogPosts}
|
|
||||||
recursive = 3
|
|
||||||
template = RssFeed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
page {
|
page {
|
||||||
headerData {
|
headerData {
|
||||||
10 = TEXT
|
10 = TEXT
|
||||||
|
@ -32,7 +5,7 @@ page {
|
||||||
wrap = <link rel="alternate" title="RSS Feed of all blog posts" type="application/rss+xml" href="|" />
|
wrap = <link rel="alternate" title="RSS Feed of all blog posts" type="application/rss+xml" href="|" />
|
||||||
typolink {
|
typolink {
|
||||||
parameter = t3://page?uid=1
|
parameter = t3://page?uid=1
|
||||||
additionalParams = &type=1533906435&sitemap=blog-posts
|
additionalParams = &type=1707321482&feed=blog-posts
|
||||||
returnLast = url
|
returnLast = url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +31,7 @@ page {
|
||||||
additionalParams.stdWrap.cObject = COA
|
additionalParams.stdWrap.cObject = COA
|
||||||
additionalParams.stdWrap.cObject {
|
additionalParams.stdWrap.cObject {
|
||||||
10 = TEXT
|
10 = TEXT
|
||||||
10.value = &type=1533906435&sitemap=blog-posts
|
10.value = &type=1707321482&feed=blog-posts
|
||||||
11 = TEXT
|
11 = TEXT
|
||||||
11.value = &category_uid=
|
11.value = &category_uid=
|
||||||
12 = TEXT
|
12 = TEXT
|
||||||
|
@ -71,18 +44,44 @@ page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rssFeed = PAGE
|
||||||
|
rssFeed {
|
||||||
|
typeNum = 1707321482
|
||||||
|
|
||||||
seo_sitemap {
|
config {
|
||||||
10 {
|
admPanel = 0
|
||||||
userFunc = DanielSiepmann\DsSite\Frontend\RssFeed\XmlSitemapRenderer->render
|
debug = 0
|
||||||
userFunc {
|
disableAllHeaderCode = 1
|
||||||
variables {
|
additionalHeaders {
|
||||||
categoryId = TEXT
|
10 {
|
||||||
categoryId.data = GP:category_uid
|
header = Content-Type: application/xml;charset=utf-8
|
||||||
categoryId.intval = 1
|
|
||||||
categoryTitle = TEXT
|
|
||||||
categoryTitle.data.dataWrap = DB : sys_category:{GP:category_uid}:title
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10 = FLUIDTEMPLATE
|
||||||
|
10 {
|
||||||
|
dataProcessing {
|
||||||
|
10 = DanielSiepmann\DsSite\Frontend\RssFeed\BlogPostsDataProvider
|
||||||
|
10 {
|
||||||
|
as = pages
|
||||||
|
table = pages
|
||||||
|
orderBy = lastUpdated DESC
|
||||||
|
selectFields = pages.uid, pages.abstract, pages.title, pages.lastUpdated
|
||||||
|
where = AND no_index = 0
|
||||||
|
pidInList = {$pageUids.blogPosts}
|
||||||
|
recursive = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variables {
|
||||||
|
categoryId = TEXT
|
||||||
|
categoryId.data = GP:category_uid
|
||||||
|
categoryId.intval = 1
|
||||||
|
categoryTitle = TEXT
|
||||||
|
categoryTitle.data.dataWrap = DB : sys_category:{GP:category_uid}:title
|
||||||
|
}
|
||||||
|
|
||||||
|
file = EXT:ds_site/Resources/Private/Templates/RssFeed.xml
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
<channel>
|
<channel>
|
||||||
<f:if condition="{settings.categoryId}">
|
<f:if condition="{categoryId}">
|
||||||
<f:then>
|
<f:then>
|
||||||
<title>Daniel Siepmann - Coding is Art - Blog Posts {settings.categoryTitle}</title>
|
<title>Daniel Siepmann - Coding is Art - Blog Posts {categoryTitle}</title>
|
||||||
<description>List of {settings.categoryTitle} blog posts at daniel-siepmann.de</description>
|
<description>List of {categoryTitle} blog posts at daniel-siepmann.de</description>
|
||||||
<link>{f:uri.typolink(parameter: 't3://page?uid=11', additionalParams: '&topic_uid={settings.categoryId}', absolute: 1)}</link>
|
<link>{f:uri.typolink(parameter: 't3://page?uid=11', additionalParams: '&topic_uid={categoryId}', absolute: 1)}</link>
|
||||||
<atom:link href="{f:uri.typolink(parameter: 't3://page?uid=1&type=1533906435', additionalParams: '&sitemap=blog-posts&category_uid={settings.categoryId}', absolute: 1)}" rel="self" type="application/rss+xml" />
|
<atom:link href="{f:uri.typolink(parameter: 't3://page?uid=1&type=1707321482', additionalParams: '&feed=blog-posts&category_uid={categoryId}', absolute: 1)}" rel="self" type="application/rss+xml" />
|
||||||
</f:then>
|
</f:then>
|
||||||
<f:else>
|
<f:else>
|
||||||
<title>Daniel Siepmann - Coding is Art - All Blog Posts</title>
|
<title>Daniel Siepmann - Coding is Art - All Blog Posts</title>
|
||||||
<description>List of blog posts at daniel-siepmann.de</description>
|
<description>List of blog posts at daniel-siepmann.de</description>
|
||||||
<link>{f:uri.typolink(parameter: 't3://page?uid=1', absolute: 1)}</link>
|
<link>{f:uri.typolink(parameter: 't3://page?uid=1', absolute: 1)}</link>
|
||||||
<atom:link href="{f:uri.typolink(parameter: 't3://page?uid=1&type=1533906435', additionalParams: '&sitemap=blog-posts', absolute: 1)}" rel="self" type="application/rss+xml" />
|
<atom:link href="{f:uri.typolink(parameter: 't3://page?uid=1&type=1707321482', additionalParams: '&feed=blog-posts', absolute: 1)}" rel="self" type="application/rss+xml" />
|
||||||
</f:else>
|
</f:else>
|
||||||
</f:if>
|
</f:if>
|
||||||
<lastBuildDate>{f:format.date(date: 'now', format: 'D, d M Y H:i:s O')}</lastBuildDate>
|
<lastBuildDate>{f:format.date(date: 'now', format: 'D, d M Y H:i:s O')}</lastBuildDate>
|
||||||
<ttl>1800</ttl>
|
<ttl>1800</ttl>
|
||||||
|
|
||||||
<f:for each="{items}" as="item">
|
<f:for each="{pages}" as="post">
|
||||||
<f:if condition="{item.data.doktype} < 200">
|
<f:if condition="{post.data.doktype} < 200">
|
||||||
{f:render(section: 'Item', arguments: {
|
{f:render(section: 'Item', arguments: {
|
||||||
item: item.data,
|
item: post.data,
|
||||||
description: item.description
|
description: post.description
|
||||||
})}
|
})}
|
||||||
</f:if>
|
</f:if>
|
||||||
</f:for>
|
</f:for>
|
Loading…
Reference in a new issue