Skip to content
Snippets Groups Projects
Commit f16f6533 authored by Kevin Ditscheid's avatar Kevin Ditscheid
Browse files

Merge branch 'feature_AutomaticRelatedNews' into 'master'

[BUGFIX] Fix bugs with fetching the related news

See merge request !44
parents 346a0ac5 7ae25569
No related branches found
No related tags found
1 merge request!44[BUGFIX] Fix bugs with fetching the related news
Showing
with 386 additions and 192 deletions
......@@ -27,32 +27,17 @@ namespace SGalinski\SgNews\Controller;
***************************************************************/
use RuntimeException;
use SGalinski\SgNews\Domain\Model\Category;
use SGalinski\SgNews\Domain\Model\News;
use SGalinski\SgNews\Service\ImageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
/**
* Abstract Controller
*/
abstract class AbstractController extends ActionController {
/**
* @var ImageService
*/
protected $imageService;
/**
* @var array
*/
protected $extensionConfiguration = [];
/**
* @var array
*/
protected $cachedSingleNews = [];
/**
* Initializes any action
*
......@@ -65,13 +50,6 @@ abstract class AbstractController extends ActionController {
parent::initializeAction();
}
/**
* @param ImageService $imageService
*/
public function injectImageService(ImageService $imageService) {
$this->imageService = $imageService;
}
/**
* Error Handler
*
......@@ -82,129 +60,6 @@ abstract class AbstractController extends ActionController {
throw new RuntimeException(parent::errorAction());
}
/**
* Returns the metadata of the given news.
*
* @param News $news
* @param Category $category
* @return array
* @throws \InvalidArgumentException
*/
protected function getMetaDataForNews(News $news, Category $category): array {
$newsId = $news->getUid();
if (isset($this->cachedSingleNews[$newsId])) {
return $this->cachedSingleNews[$newsId];
}
$fileRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\FileRepository::class);
$fileObjects = $fileRepository->findByRelation('pages', 'media', $news->getUid());
$singleNewsImageData = $this->getDataForSingleViewImage($news, $category);
$teaserImageData = $this->getDataForTeaserImage($news, $category);
// Use single news image data for teaser image data, if the teaser imaga data are empty.
$teaserIsEmpty = $teaserImageData['teaserImage'] === NULL && $teaserImageData['teaserImageObject'] === NULL;
$singleNewsIsEmpty = $singleNewsImageData['image'] === NULL && $singleNewsImageData['imageObject'] === NULL;
if ($teaserIsEmpty && !$singleNewsIsEmpty) {
$teaserImageData = [
'teaserImage' => $singleNewsImageData['image'],
'teaserImageObject' => $singleNewsImageData['imageObject'],
];
}
$newsRecord = array_merge(
[
'category' => $category,
'news' => $news,
],
$singleNewsImageData,
$teaserImageData,
['media' => $fileObjects]
);
$this->cachedSingleNews[$newsId] = $newsRecord;
return $newsRecord;
}
/**
* Returns the single view image data as an array for the given news and category as fallback.
*
* @param News $news
* @param Category $category
* @return array
* @throws \InvalidArgumentException
*/
protected function getDataForSingleViewImage(News $news, Category $category): array {
/** @var FileReference $singleNewsImage */
$singleNewsImage = $singleNewsImageObject = NULL;
$singleNewsImages = $news->getTeaser2Image();
if (count($singleNewsImages)) {
$singleNewsImage = $singleNewsImages->current();
} else {
$categoryImages = $category->getTeaser2Image();
if (count($categoryImages)) {
$singleNewsImage = $categoryImages->current();
}
}
if ($singleNewsImage) {
$singleNewsImageObject = $singleNewsImage;
$originalResource = $singleNewsImage->getOriginalResource();
if ($originalResource) {
$singleNewsImage = $originalResource->getPublicUrl();
}
if ($singleNewsImage) {
$singleNewsImage = $GLOBALS['TSFE']->absRefPrefix . $singleNewsImage;
}
}
return [
'image' => $singleNewsImage,
'imageObject' => $singleNewsImageObject,
];
}
/**
* Returns the teaser image data as an array for the given news and category as fallback.
*
* @param News $news
* @param Category $category
* @return array
* @throws \InvalidArgumentException
*/
protected function getDataForTeaserImage(News $news, Category $category): array {
/** @var FileReference $teaserImage */
$teaserImage = $teaserImageObject = NULL;
$teaserImages = $news->getTeaser1Image();
if (count($teaserImages)) {
$teaserImage = $teaserImages->current();
} else {
$categoryImages = $category->getTeaser1Image();
if (count($categoryImages)) {
$teaserImage = $categoryImages->current();
}
}
if ($teaserImage) {
$teaserImageObject = $teaserImage;
$originalResource = $teaserImage->getOriginalResource();
if ($originalResource) {
$teaserImage = $originalResource->getPublicUrl();
}
if ($teaserImage) {
$teaserImage = $GLOBALS['TSFE']->absRefPrefix . $teaserImage;
}
}
return [
'teaserImage' => $teaserImage,
'teaserImageObject' => $teaserImageObject,
];
}
/**
* Calculate the pagination offset
*
......
......@@ -31,6 +31,7 @@ use SGalinski\SgNews\Domain\Model\News;
use SGalinski\SgNews\Domain\Repository\CategoryRepository;
use SGalinski\SgNews\Domain\Repository\NewsRepository;
use SGalinski\SgNews\Domain\Repository\TagRepository;
use SGalinski\SgNews\Domain\Service\NewsService;
use SGalinski\SgNews\Service\ConfigurationService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
......@@ -53,6 +54,11 @@ class LatestController extends AbstractController {
*/
protected $newsRepository;
/**
* @var NewsService
*/
protected $newsService;
/**
* Renders the news overview
*
......@@ -96,7 +102,7 @@ class LatestController extends AbstractController {
$categories[$categoryUid] = $category;
}
$newsMetaData[] = $this->getMetaDataForNews($latestNewsEntry, $category);
$newsMetaData[] = $this->newsService->getMetaDataForNews($latestNewsEntry, $category);
// Make sure, that the amount is the same as the configured limit.
if (count($newsMetaData) >= $limit) {
break;
......@@ -127,4 +133,11 @@ class LatestController extends AbstractController {
public function injectTagRepository(TagRepository $tagRepository) {
$this->tagRepository = $tagRepository;
}
/**
* @param NewsService $newsService
*/
public function injectNewsService(NewsService $newsService) {
$this->newsService = $newsService;
}
}
......@@ -30,6 +30,7 @@ use SGalinski\SgNews\Domain\Model\News;
use SGalinski\SgNews\Domain\Repository\CategoryRepository;
use SGalinski\SgNews\Domain\Repository\NewsRepository;
use SGalinski\SgNews\Domain\Repository\TagRepository;
use SGalinski\SgNews\Domain\Service\NewsService;
use SGalinski\SgNews\Service\ConfigurationService;
use SGalinski\SgNews\Service\HeaderMetaDataService;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
......@@ -57,6 +58,11 @@ class ListByCategoryController extends AbstractController {
*/
protected $newsRepository;
/**
* @var NewsService
*/
protected $newsService;
/**
* @param CategoryRepository $categoryRepository
*/
......@@ -79,6 +85,13 @@ class ListByCategoryController extends AbstractController {
$this->tagRepository = $tagRepository;
}
/**
* @param NewsService $newsService
*/
public function injectNewsService(NewsService $newsService) {
$this->newsService = $newsService;
}
/**
* Initialize the indexAction to set the currentPageBrowserPage parameter
*
......@@ -164,7 +177,7 @@ class ListByCategoryController extends AbstractController {
foreach ($news as $newsEntry) {
/** @var News $newsEntry */
$data = $this->getMetaDataForNews($newsEntry, $categories[$newsEntry->getPid()]);
$data = $this->newsService->getMetaDataForNews($newsEntry, $categories[$newsEntry->getPid()]);
$newsMetaData[] = $data;
if (!$headerSet) {
......
......@@ -32,6 +32,7 @@ use SGalinski\SgNews\Domain\Model\News;
use SGalinski\SgNews\Domain\Repository\AuthorRepository;
use SGalinski\SgNews\Domain\Repository\CategoryRepository;
use SGalinski\SgNews\Domain\Repository\NewsRepository;
use SGalinski\SgNews\Domain\Service\NewsService;
use SGalinski\SgSeo\Service\HeadTagService;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
......@@ -40,6 +41,18 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
* News Author List Controller
*/
class NewsByAuthorController extends AbstractController {
/**
* @var NewsService
*/
protected $newsService;
/**
* @param NewsService $newsService
*/
public function injectNewsService(NewsService $newsService) {
$this->newsService = $newsService;
}
/**
* Renders the news author list.
*
......@@ -118,7 +131,7 @@ class NewsByAuthorController extends AbstractController {
$categories[$categoryId] = $category;
}
$newsMetaData[] = $this->getMetaDataForNews($newsEntry, $categories[$categoryId]);
$newsMetaData[] = $this->newsService->getMetaDataForNews($newsEntry, $categories[$categoryId]);
}
}
......
......@@ -31,6 +31,7 @@ use SGalinski\SgNews\Domain\Model\News;
use SGalinski\SgNews\Domain\Repository\CategoryRepository;
use SGalinski\SgNews\Domain\Repository\NewsRepository;
use SGalinski\SgNews\Domain\Repository\TagRepository;
use SGalinski\SgNews\Domain\Service\NewsService;
use SGalinski\SgNews\Service\ConfigurationService;
use SGalinski\SgNews\Service\HeaderMetaDataService;
use TYPO3\CMS\Core\Http\ImmediateResponseException;
......@@ -60,6 +61,11 @@ class OverviewController extends AbstractController {
*/
protected $newsRepository;
/**
* @var NewsService
*/
protected $newsService;
/**
* @param CategoryRepository $categoryRepository
*/
......@@ -82,6 +88,13 @@ class OverviewController extends AbstractController {
$this->tagRepository = $tagRepository;
}
/**
* @param NewsService $newsService
*/
public function injectNewsService(NewsService $newsService) {
$this->newsService = $newsService;
}
/**
* Initialize the overviewAction to set the currentPageBrowserPage parameter
*
......@@ -216,7 +229,7 @@ class OverviewController extends AbstractController {
$newsEntry->getPid()
) ?? $this->categoryRepository->findByUid($newsEntry->getPid());
$newsCategoryId = $newsCategory->getUid();
$newsMetaData = $this->getMetaDataForNews($newsEntry, $newsCategory);
$newsMetaData = $this->newsService->getMetaDataForNews($newsEntry, $newsCategory);
if ((int) $this->settings['groupBy'] === 1) {
if (!$areCategoriesCreated) {
......@@ -353,7 +366,7 @@ class OverviewController extends AbstractController {
$category = $this->categoryRepository->findByUid($highlightedNews->getPid());
$highlightedNewsMetaData = NULL;
if ($category) {
$highlightedNewsMetaData = $this->getMetaDataForNews($highlightedNews, $category);
$highlightedNewsMetaData = $this->newsService->getMetaDataForNews($highlightedNews, $category);
}
if (!version_compare(ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) {
......@@ -470,7 +483,7 @@ class OverviewController extends AbstractController {
);
foreach ($news as $newsEntry) {
/** @var News $newsEntry */
$data = $this->getMetaDataForNews($newsEntry, $categoriesById[$newsEntry->getPid()]);
$data = $this->newsService->getMetaDataForNews($newsEntry, $categoriesById[$newsEntry->getPid()]);
$newsMetaData[] = $data;
}
......
......@@ -31,6 +31,7 @@ use SGalinski\SgNews\Domain\Model\News;
use SGalinski\SgNews\Domain\Repository\CategoryRepository;
use SGalinski\SgNews\Domain\Repository\NewsRepository;
use SGalinski\SgNews\Domain\Repository\TagRepository;
use SGalinski\SgNews\Domain\Service\NewsService;
use SGalinski\SgNews\Service\HeaderMetaDataService;
use TYPO3\CMS\Core\Charset\CharsetConverter;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
......@@ -59,6 +60,11 @@ class SingleViewController extends AbstractController {
*/
protected $characterSetConverter;
/**
* @var NewsService
*/
protected $newsService;
/**
* Renders the news single view
*
......@@ -92,7 +98,7 @@ class SingleViewController extends AbstractController {
// $similarNewsMetaData[] = $this->getMetaDataForNews($similarNewsEntry, $category);
// }
$newsMetaData = $this->getMetaDataForNews($news, $newsCategory);
$newsMetaData = $this->newsService->getMetaDataForNews($news, $newsCategory);
if (!version_compare(ExtensionManagementUtility::getExtensionVersion('sg_seo'), '5.0.0', '>=')) {
if ($newsMetaData['image']) {
HeaderMetaDataService::addOgImageToHeader($newsMetaData['image']);
......@@ -145,4 +151,11 @@ class SingleViewController extends AbstractController {
public function injectTagRepository(TagRepository $tagRepository) {
$this->tagRepository = $tagRepository;
}
/**
* @param NewsService $newsService
*/
public function injectNewsService(NewsService $newsService) {
$this->newsService = $newsService;
}
}
......@@ -536,29 +536,40 @@ class NewsRepository extends AbstractRepository {
$constraints[] = $qb->expr()->eq('pid', $news->getPid());
}
if ($limit > 0) {
$qb->setMaxResults($limit);
}
// here we fetch the lastUpdated of the $limit amount of news with newer lastUpdated dates
$result = $qb->select('lastUpdated')
->from('pages')
->from('pages', 'pages')
->where(
$qb->expr()->eq('doktype', $qb->createNamedParameter(News::DOK_TYPE_NEWS, Connection::PARAM_INT)),
$qb->expr()->gt('lastUpdated', $news->getLastUpdated()->getTimestamp()),
$qb->expr()->andX(...$constraints)
)
->setMaxResults($limit)
$qb->expr()->gte('lastUpdated', $news->getLastUpdated()->getTimestamp())
)->andWhere(...$constraints)
->orderBy('lastUpdated', 'desc')
->execute();
$newest = $result->fetchOne();
// Here we fetch the lastUpdated of the $limit amount of news with older lastUpdated dates
$result = $qb->orderBy('lastUpdated', 'asc')->execute();
$result = $qb->where(
$qb->expr()->eq('doktype', $qb->createNamedParameter(News::DOK_TYPE_NEWS, Connection::PARAM_INT)),
$qb->expr()->lte('lastUpdated', $news->getLastUpdated()->getTimestamp())
)->andWhere(...$constraints)
->orderBy('lastUpdated', 'asc')
->execute();
$oldest = $result->fetchOne();
$query = $this->createQuery();
$query->getQuerySettings()->setRespectStoragePage(FALSE);
$query->setOrderings([
'crdate' => QueryInterface::ORDER_DESCENDING
'lastUpdated' => QueryInterface::ORDER_DESCENDING
]);
$constraints = [];
$constraints = [
$query->logicalNot(
$query->equals('uid', $news->getUid())
)
];
if ($newest) {
$constraints[] = $query->lessThanOrEqual('lastUpdated', $newest);
}
......@@ -572,9 +583,12 @@ class NewsRepository extends AbstractRepository {
// "around" the given news, where newer news are preferred due to the ordering.
$tags = $news->getTags();
if ($tags->count() > 0) {
$tagConstraints = [];
foreach ($tags as $tag) {
$constraints[] = $query->contains('tags', $tag);
$tagConstraints[] = $query->contains('tags', $tag);
}
$constraints[] = $query->logicalOr($tagConstraints);
} else {
$constraints[] = $query->equals('pid', $news->getPid());
}
......
<?php
namespace SGalinski\SgNews\Domain\Service;
/***************************************************************
* Copyright notice
*
* (c) sgalinski Internet Services (https://www.sgalinski.de)
*
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project 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 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script 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.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use SGalinski\SgNews\Domain\Model\Category;
use SGalinski\SgNews\Domain\Model\News;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Domain\Model\FileReference;
use TYPO3\CMS\Core\Resource\FileRepository;
/**
* This service takes care of meta data generation for the news objects
*/
class NewsService implements SingletonInterface {
/**
* @var array
*/
protected $cachedSingleNews = [];
/**
* Returns the metadata of the given news.
*
* @param News $news
* @param Category $category
* @return array
* @throws \InvalidArgumentException
*/
public function getMetaDataForNews(News $news, Category $category): array {
$newsId = $news->getUid();
if (isset($this->cachedSingleNews[$newsId])) {
return $this->cachedSingleNews[$newsId];
}
$fileRepository = GeneralUtility::makeInstance(FileRepository::class);
$fileObjects = $fileRepository->findByRelation('pages', 'media', $news->getUid());
$singleNewsImageData = $this->getDataForSingleViewImage($news, $category);
$teaserImageData = $this->getDataForTeaserImage($news, $category);
// Use single news image data for teaser image data, if the teaser imaga data are empty.
$teaserIsEmpty = $teaserImageData['teaserImage'] === NULL && $teaserImageData['teaserImageObject'] === NULL;
$singleNewsIsEmpty = $singleNewsImageData['image'] === NULL && $singleNewsImageData['imageObject'] === NULL;
if ($teaserIsEmpty && !$singleNewsIsEmpty) {
$teaserImageData = [
'teaserImage' => $singleNewsImageData['image'],
'teaserImageObject' => $singleNewsImageData['imageObject'],
];
}
$newsRecord = array_merge(
[
'category' => $category,
'news' => $news,
],
$singleNewsImageData,
$teaserImageData,
['media' => $fileObjects]
);
$this->cachedSingleNews[$newsId] = $newsRecord;
return $newsRecord;
}
/**
* Returns the single view image data as an array for the given news and category as fallback.
*
* @param News $news
* @param Category $category
* @return array
* @throws \InvalidArgumentException
*/
public function getDataForSingleViewImage(News $news, Category $category): array {
/** @var FileReference $singleNewsImage */
$singleNewsImage = $singleNewsImageObject = NULL;
$singleNewsImages = $news->getTeaser2Image();
if (count($singleNewsImages)) {
$singleNewsImage = $singleNewsImages->current();
} else {
$categoryImages = $category->getTeaser2Image();
if (count($categoryImages)) {
$singleNewsImage = $categoryImages->current();
}
}
if ($singleNewsImage) {
$singleNewsImageObject = $singleNewsImage;
$originalResource = $singleNewsImage->getOriginalResource();
if ($originalResource) {
$singleNewsImage = $originalResource->getPublicUrl();
}
if ($singleNewsImage) {
$singleNewsImage = $GLOBALS['TSFE']->absRefPrefix . $singleNewsImage;
}
}
return [
'image' => $singleNewsImage,
'imageObject' => $singleNewsImageObject,
];
}
/**
* Returns the teaser image data as an array for the given news and category as fallback.
*
* @param News $news
* @param Category $category
* @return array
* @throws \InvalidArgumentException
*/
public function getDataForTeaserImage(News $news, Category $category): array {
/** @var FileReference $teaserImage */
$teaserImage = $teaserImageObject = NULL;
$teaserImages = $news->getTeaser1Image();
if (count($teaserImages)) {
$teaserImage = $teaserImages->current();
} else {
$categoryImages = $category->getTeaser1Image();
if (count($categoryImages)) {
$teaserImage = $categoryImages->current();
}
}
if ($teaserImage) {
$teaserImageObject = $teaserImage;
$originalResource = $teaserImage->getOriginalResource();
if ($originalResource) {
$teaserImage = $originalResource->getPublicUrl();
}
if ($teaserImage) {
$teaserImage = $GLOBALS['TSFE']->absRefPrefix . $teaserImage;
}
}
return [
'teaserImage' => $teaserImage,
'teaserImageObject' => $teaserImageObject,
];
}
}
......@@ -2,8 +2,11 @@
namespace SGalinski\SgNews\ViewHelpers;
use SGalinski\SgNews\Domain\Repository\CategoryRepository;
use SGalinski\SgNews\Domain\Repository\NewsRepository;
use SGalinski\SgNews\Domain\Service\NewsService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\ObjectStorage;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
......@@ -13,6 +16,11 @@ use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
class RelatedViewHelper extends AbstractViewHelper {
use CompileWithRenderStatic;
/**
* @var bool
*/
protected $escapeOutput = false;
/**
* Initialize the view helper arguments
*/
......@@ -23,12 +31,30 @@ class RelatedViewHelper extends AbstractViewHelper {
'The news record from which to find related news',
TRUE
);
$this->registerArgument('limit', 'int', 'Limit the amount of related news to display', FALSE, 5);
$this->registerArgument('as', 'string', 'The name of the iteration variable', TRUE);
$this->registerArgument(
'limit',
'int',
'Limit the amount of related news to display',
FALSE,
5
);
$this->registerArgument(
'as',
'string',
'The name of the iteration variable',
TRUE
);
$this->registerArgument(
'iteration', 'string',
'The name of the variable to store iteration information (index, cycle, isFirst, isLast, isEven, isOdd)'
);
$this->registerArgument(
'relatedNews',
ObjectStorage::class,
'An optional list of related news to take instead of finding some via the news repository',
FALSE,
NULL
);
}
/**
......@@ -44,21 +70,34 @@ class RelatedViewHelper extends AbstractViewHelper {
public static function renderStatic(
array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext
) {
$newsService = GeneralUtility::makeInstance(NewsService::class);
$categoryRepository = GeneralUtility::makeInstance(CategoryRepository::class);
$templateVariableContainer = $renderingContext->getVariableProvider();
$news = $arguments['news'];
$newsRepository = GeneralUtility::makeInstance(NewsRepository::class);
$related = $newsRepository->findRelated($news);
if ($arguments['relatedNews']) {
$related = $arguments['relatedNews'];
} else {
$related = $newsRepository->findRelated($news, (int) $arguments['limit']);
}
if (isset($arguments['iteration'])) {
$iterationData = [
'index' => 0,
'cycle' => 1,
'total' => count($arguments['each'])
'total' => $related->count()
];
}
$output = '';
$categories = [];
foreach ($related as $relatedNews) {
$templateVariableContainer->add($arguments['as'], $relatedNews);
if (!isset($categories[$relatedNews->getPid()])) {
$categories[$relatedNews->getPid()] = $categoryRepository->findByUid($relatedNews->getPid());
}
$newsMetaData = $newsService->getMetaDataForNews($relatedNews, $categories[$relatedNews->getPid()]);
$templateVariableContainer->add($arguments['as'], $newsMetaData);
if (isset($iterationData)) {
$iterationData['isFirst'] = $iterationData['cycle'] === 1;
$iterationData['isLast'] = $iterationData['cycle'] === $iterationData['total'];
......
......@@ -19,5 +19,8 @@ plugin.tx_sgnews {
# sort direction (DESC / ASC)
sortDirection = DESC
# This enables the output of related news in regards to the news category or tags
enableAutomaticRelatedNews = 0
}
}
......@@ -109,6 +109,9 @@ plugin.tx_sgnews {
# The logo value for the structured data implementation (see single view template)
publisherLogo =
# This enables the output of related news in regards to the news category or tags
enableAutomaticRelatedNews = {$plugin.tx_sgnews.settings.enableAutomaticRelatedNews}
}
features {
......
{namespace sg=SGalinski\SgNews\ViewHelpers}
<f:comment>
<!--
Usage Example:
<f:render partial="Teaser" arguments="{
newsMetaData: newsMetaData,
headerTag: '<h3>',
closingHeaderTag: '</h3>',
showCategory: 1
}" />
newsMetaData -> news element
headerTag -> hierarchy type of the header tag
showCategory -> defines if the category may be shown
Use <f:debug>{_all}</f:debug> to see all parameters and fields.
-->
</f:comment>
<f:link.page pageUid="{news.uid}" class="tx-sgnews-teaser">
<f:if condition="{news.teaser1Image}">
<f:for each="{news.teaser1Image}" as="teaserImage">
<div class="tx-sgnews-teaser-image tx-sgnews-teaser-image-stretched"
style="background-image: url({f:uri.image(image: teaserImage)});"></div>
</f:for>
</f:if>
<div class="tx-sgnews-teaser-inner">
<div class="tx-sgnews-teaser-title">
{headerTag -> f:format.raw()}
{news.subtitleWithFallbackToTitle}
{closingHeaderTag -> f:format.raw()}
</div>
</div>
</f:link.page>
......@@ -88,12 +88,12 @@
</div>
</div>
</section>
</div>
<section class="content">
<div class="container">
<div class="tx-sgnews-single">
<div class="tx-sgnews-single-container">
<ul class="tx-sgnews-single-container">
<f:alias
map="{content: '{f:cObject(typoscriptObjectPath: \'{f:if(condition: \\\'{newsMetaData.news.contentFromAnotherPage}\\\', then: \\\'lib.contentFromAnotherPage\\\', else: \\\'lib.mainContent\\\')}\')}'}">
<div class="tx-sgnews-single-content">
......@@ -199,38 +199,50 @@
<f:if condition="{newsMetaData.news.relatedNews}">
<f:then>
<div class="tx-sgnews-single-related">
<div class="tx-sgnews-single-related tx-sgnews-categories">
<h3>
<f:translate key="frontend.singleview.relatedArticles"/>
</h3>
<ul>
<f:for each="{newsMetaData.news.relatedNews}" as="relatedNewsEntry">
<li>
<a href="{f:uri.page(pageUid: '{relatedNewsEntry.uid}')}">
{relatedNewsEntry.subtitleWithFallbackToTitle}
</a>
<ul class="tx-sgnews-list tx-sgnews-overview row">
<sg:related news="{newsMetaData.news}"
relatedNews="{newsMetaData.news.relatedNews}"
as="relatedNewsEntry">
<li class="col-md-4 col-sm-6 col-xs-12">
<f:render partial="Teaser" arguments="{
newsMetaData: relatedNewsEntry,
headerTag: '<h2>',
closingHeaderTag: '</h2>',
showCategory: '1'
}" />
</li>
</f:for>
</sg:related>
</ul>
</div>
</f:then>
<f:else>
<div class="tx-sgnews-single-related">
<h3>
<f:translate key="frontend.singleview.relatedArticles"/>
</h3>
<ul>
<sg:related news="{newsMetaData.news}" limit="5" as="relatedNewsEntry">
<li>
<a href="{f:uri.page(pageUid: '{relatedNewsEntry.uid}')}">
{relatedNewsEntry.subtitleWithFallbackToTitle}
</a>
</li>
</sg:related>
</ul>
</div>
<f:if condition="{settings.enableAutomaticRelatedNews}">
<sg:related news="{newsMetaData.news}" iteration="iterator" limit="3" as="relatedNewsEntry">
<f:if condition="{iterator.isFirst}">
<div class="tx-sgnews-single-related tx-sgnews-categories">
<h3>
<f:translate key="frontend.singleview.relatedArticles"/>
</h3>
<ul class="tx-sgnews-list tx-sgnews-overview row">
</f:if>
<li class="col-md-4 col-sm-6 col-xs-12">
<f:render partial="Teaser" arguments="{
newsMetaData: relatedNewsEntry,
headerTag: '<h2>',
closingHeaderTag: '</h2>',
showCategory: '1'
}" />
</li>
<f:if condition="{iterator.isLast}">
</ul>
</div>
</f:if>
</sg:related>
</f:if>
</f:else>
</f:if>
</div>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment