From cd5e5582d3aa1a0c7fb55dc70ea96a610078853d Mon Sep 17 00:00:00 2001 From: Stefan Galinski <stefan@sgalinski.de> Date: Fri, 22 Apr 2022 22:46:27 +0200 Subject: [PATCH] [BUGFIX] Hotfix the related news feature (still almost completely broken) --- Classes/Domain/Repository/NewsRepository.php | 23 ++--- Classes/ViewHelpers/RelatedViewHelper.php | 73 ++++++++------ .../Templates/SingleView/SingleView.html | 95 ++++++++++++------- 3 files changed, 113 insertions(+), 78 deletions(-) diff --git a/Classes/Domain/Repository/NewsRepository.php b/Classes/Domain/Repository/NewsRepository.php index c854896..7d8011d 100644 --- a/Classes/Domain/Repository/NewsRepository.php +++ b/Classes/Domain/Repository/NewsRepository.php @@ -514,22 +514,24 @@ class NewsRepository extends AbstractRepository { * @param News $news The news to find related news to * @param int $limit Limit the amount of related news * @return QueryResultInterface + * @throws \Doctrine\DBAL\Driver\Exception + * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ - public function findRelated(News $news, int $limit = 0) { + public function findRelated(News $news, int $limit = 0): QueryResultInterface { $connection = $this->getConnection(); $qb = $connection->createQueryBuilder(); // We need to build the constraint for the tags/categories $constraints = []; $tags = $news->getTags(); if ($tags->count() > 0) { + $qb->leftJoin('pages', 'sys_category_record_mm', 'tags', 'pages.uid=tags.uid_foreign'); $tagConstraints = []; foreach ($tags as $tag) { - $qb->leftJoin('pages', 'sys_category_records_mm', 'tags', 'pages.uid=tags.uid_foreign'); $tagConstraints[] = $qb->expr()->eq('tags.uid_local', $tag->getUid()); } $constraints[] = $qb->expr()->eq('tags.tablenames', $qb->createNamedParameter('pages')); $constraints[] = $qb->expr()->eq('tags.fieldname', $qb->createNamedParameter('tx_sgnews_tags')); - $constraints[] = $qb->expr()->orX($tagConstraints); + $constraints[] = $qb->expr()->orX(...$tagConstraints); } else { $constraints[] = $qb->expr()->eq('pid', $news->getPid()); } @@ -548,16 +550,7 @@ class NewsRepository extends AbstractRepository { $newest = $result->fetchOne(); // Here we fetch the lastUpdated of the $limit amount of news with older lastUpdated dates - $result = $qb->select('lastUpdated') - ->from('pages') - ->where( - $qb->expr()->eq('doktype', $qb->createNamedParameter(News::DOK_TYPE_NEWS, Connection::PARAM_INT)), - $qb->expr()->lt('lastUpdated', $news->getLastUpdated()->getTimestamp()), - $qb->expr()->andX(...$constraints) - ) - ->setMaxResults($limit) - ->orderBy('lastUpdated', 'asc') - ->execute(); + $result = $qb->orderBy('lastUpdated', 'asc')->execute(); $oldest = $result->fetchOne(); $query = $this->createQuery(); @@ -586,9 +579,7 @@ class NewsRepository extends AbstractRepository { $constraints[] = $query->equals('pid', $news->getPid()); } - $query->matching( - $constraints - ); + $query->matching($query->logicalAnd($constraints)); if ($limit > 0) { $query->setLimit($limit); } diff --git a/Classes/ViewHelpers/RelatedViewHelper.php b/Classes/ViewHelpers/RelatedViewHelper.php index f49aeec..6a5ec43 100644 --- a/Classes/ViewHelpers/RelatedViewHelper.php +++ b/Classes/ViewHelpers/RelatedViewHelper.php @@ -2,10 +2,17 @@ namespace SGalinski\SgNews\ViewHelpers; +use SGalinski\SgNews\Domain\Repository\NewsRepository; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; +/** + * Renders related news based on the current news + */ class RelatedViewHelper extends AbstractViewHelper { + use CompileWithRenderStatic; + /** * Initialize the view helper arguments */ @@ -18,45 +25,55 @@ class RelatedViewHelper extends AbstractViewHelper { ); $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( + 'iteration', 'string', + 'The name of the variable to store iteration information (index, cycle, isFirst, isLast, isEven, isOdd)' + ); } /** - * Render the ViewHelper * It works like the for-ViewHelper by running through the child content and adding the related news records to it * + * @param array $arguments + * @param \Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext * @return string + * @throws \Doctrine\DBAL\Driver\Exception + * @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException */ - public function render() { - $news = $this->arguments['news']; + public static function renderStatic( + array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext + ) { + $templateVariableContainer = $renderingContext->getVariableProvider(); + $news = $arguments['news']; $newsRepository = GeneralUtility::makeInstance(NewsRepository::class); $related = $newsRepository->findRelated($news); - $templateVariableContainer = $this->renderingContext->getVariableProvider(); + if (isset($arguments['iteration'])) { + $iterationData = [ + 'index' => 0, + 'cycle' => 1, + 'total' => count($arguments['each']) + ]; + } + $output = ''; - if (isset($this->arguments['iteration'])) { - $iterationData = [ - 'index' => 0, - 'cycle' => 1, - 'total' => count($related) - ]; - } foreach ($related as $relatedNews) { - $templateVariableContainer->add($this->arguments['as'], $relatedNews); - if (isset($this->arguments['iteration'])) { - $iterationData['isFirst'] = $iterationData['cycle'] === 1; - $iterationData['isLast'] = $iterationData['cycle'] === $iterationData['total']; - $iterationData['isEven'] = $iterationData['cycle'] % 2 === 0; - $iterationData['isOdd'] = !$iterationData['isEven']; - $templateVariableContainer->add($this->arguments['iteration'], $iterationData); - $iterationData['index']++; - $iterationData['cycle']++; - } + $templateVariableContainer->add($arguments['as'], $relatedNews); + if (isset($iterationData)) { + $iterationData['isFirst'] = $iterationData['cycle'] === 1; + $iterationData['isLast'] = $iterationData['cycle'] === $iterationData['total']; + $iterationData['isEven'] = $iterationData['cycle'] % 2 === 0; + $iterationData['isOdd'] = !$iterationData['isEven']; + $templateVariableContainer->add($arguments['iteration'], $iterationData); + $iterationData['index']++; + $iterationData['cycle']++; + } - $output .= $this->renderChildren(); - $templateVariableContainer->remove($this->arguments['as']); - if (isset($this->arguments['iteration'])) { - $templateVariableContainer->remove($this->arguments['iteration']); - } + $output .= $renderChildrenClosure(); + $templateVariableContainer->remove($arguments['as']); + if (isset($arguments['iteration'])) { + $templateVariableContainer->remove($arguments['iteration']); + } } return $output; diff --git a/Resources/Private/Templates/SingleView/SingleView.html b/Resources/Private/Templates/SingleView/SingleView.html index ab6e723..7ee717d 100644 --- a/Resources/Private/Templates/SingleView/SingleView.html +++ b/Resources/Private/Templates/SingleView/SingleView.html @@ -1,4 +1,4 @@ -<f:layout name="Default" /> +<f:layout name="Default"/> {namespace base=SGalinski\ProjectBase\ViewHelpers} {namespace sg=SGalinski\SgNews\ViewHelpers} @@ -10,14 +10,15 @@ <div class="intro-section"> <section class="dark-bg"> - <div class="tx-sgnews-single-header {f:if(condition: newsMetaData.imageObject, then: 'tx-sgnews-single-header-image')}"> + <div + class="tx-sgnews-single-header {f:if(condition: newsMetaData.imageObject, then: 'tx-sgnews-single-header-image')}"> <f:if condition="{newsMetaData.imageObject}"> <div class="tx-sgnews-single-image"> <picture> <source media="(max-width: 1200px)" - srcset="{f:uri.image(src: newsMetaData.imageObject.uid, treatIdAsReference: '1', width: '1200c', height: '403c', cropVariant: 'small')}"> + srcset="{f:uri.image(src: newsMetaData.imageObject.uid, treatIdAsReference: '1', width: '1200c', height: '403c', cropVariant: 'small')}"> <f:image image="{newsMetaData.imageObject}" alt="" width="1845c" - height="619c" loading="lazy"/> + height="619c" loading="lazy"/> </picture> </div> </f:if> @@ -30,11 +31,15 @@ <div class="tx-sgnews-teaser-meta"> <f:if condition="{authorCount}"> <span class="author"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="#FFF" d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z" /></svg> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path + fill="#FFF" + d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"/></svg> </span> - <f:for each="{newsMetaData.news.newsAuthor}" as="newsAuthor" iteration="iterator"> - <f:alias map="{divider: '{f:if(condition: \'{iterator.cycle} < {authorCount}\', then: \',\')}'}"> + <f:for each="{newsMetaData.news.newsAuthor}" as="newsAuthor" + iteration="iterator"> + <f:alias + map="{divider: '{f:if(condition: \'{iterator.cycle} < {authorCount}\', then: \',\')}'}"> <a class="tx-sgnews-teaser-meta-author" href="#author{newsAuthor.uid}"> <f:if condition="{newsAuthor.name}"> {newsAuthor.name}{divider} @@ -46,26 +51,32 @@ <f:if condition="{newsMetaData.news.location}"> <span class="location"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="#FFF" d="M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0z" /></svg> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path + fill="#FFF" + d="M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0z"/></svg> {newsMetaData.news.location} </span> </f:if> <span class="date"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#FFF" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm57.1 350.1L224.9 294c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h48c6.6 0 12 5.4 12 12v137.7l63.5 46.2c5.4 3.9 6.5 11.4 2.6 16.8l-28.2 38.8c-3.9 5.3-11.4 6.5-16.8 2.6z" /></svg> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#FFF" + d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm57.1 350.1L224.9 294c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h48c6.6 0 12 5.4 12 12v137.7l63.5 46.2c5.4 3.9 6.5 11.4 2.6 16.8l-28.2 38.8c-3.9 5.3-11.4 6.5-16.8 2.6z"/></svg> <f:format.date format="{f:translate(key:'frontend.dateformat')}">{newsMetaData.news.lastUpdated}</f:format.date> </span> <span class="category"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#FFF" d="M0 252.118V48C0 21.49 21.49 0 48 0h204.118a48 48 0 0 1 33.941 14.059l211.882 211.882c18.745 18.745 18.745 49.137 0 67.882L293.823 497.941c-18.745 18.745-49.137 18.745-67.882 0L14.059 286.059A48 48 0 0 1 0 252.118zM112 64c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z" /></svg> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#FFF" + d="M0 252.118V48C0 21.49 21.49 0 48 0h204.118a48 48 0 0 1 33.941 14.059l211.882 211.882c18.745 18.745 18.745 49.137 0 67.882L293.823 497.941c-18.745 18.745-49.137 18.745-67.882 0L14.059 286.059A48 48 0 0 1 0 252.118zM112 64c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z"/></svg> <a href="{f:uri.page(pageUid: '{newsMetaData.category.uid}')}"> {newsMetaData.category.subtitleWithFallbackToTitle} </a> </span> <f:if condition="{newsMetaData.news.tags}"> - <br /> + <br/> <span class="tags"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="#FFF" d="M497.941 225.941L286.059 14.059A48 48 0 0 0 252.118 0H48C21.49 0 0 21.49 0 48v204.118a48 48 0 0 0 14.059 33.941l211.882 211.882c18.744 18.745 49.136 18.746 67.882 0l204.118-204.118c18.745-18.745 18.745-49.137 0-67.882zM112 160c-26.51 0-48-21.49-48-48s21.49-48 48-48 48 21.49 48 48-21.49 48-48 48zm513.941 133.823L421.823 497.941c-18.745 18.745-49.137 18.745-67.882 0l-.36-.36L527.64 323.522c16.999-16.999 26.36-39.6 26.36-63.64s-9.362-46.641-26.36-63.64L331.397 0h48.721a48 48 0 0 1 33.941 14.059l211.882 211.882c18.745 18.745 18.745 49.137 0 67.882z" /></svg> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path + fill="#FFF" + d="M497.941 225.941L286.059 14.059A48 48 0 0 0 252.118 0H48C21.49 0 0 21.49 0 48v204.118a48 48 0 0 0 14.059 33.941l211.882 211.882c18.744 18.745 49.136 18.746 67.882 0l204.118-204.118c18.745-18.745 18.745-49.137 0-67.882zM112 160c-26.51 0-48-21.49-48-48s21.49-48 48-48 48 21.49 48 48-21.49 48-48 48zm513.941 133.823L421.823 497.941c-18.745 18.745-49.137 18.745-67.882 0l-.36-.36L527.64 323.522c16.999-16.999 26.36-39.6 26.36-63.64s-9.362-46.641-26.36-63.64L331.397 0h48.721a48 48 0 0 1 33.941 14.059l211.882 211.882c18.745 18.745 18.745 49.137 0 67.882z"/></svg> <f:for each="{newsMetaData.news.tags}" as="tag" iteration="it"> {tag.title}<f:if condition="{it.isLast}"><f:else>, </f:else></f:if> </f:for> @@ -83,14 +94,16 @@ <div class="container"> <div class="tx-sgnews-single"> <div class="tx-sgnews-single-container"> - <f:alias map="{content: '{f:cObject(typoscriptObjectPath: \'{f:if(condition: \\\'{newsMetaData.news.contentFromAnotherPage}\\\', then: \\\'lib.contentFromAnotherPage\\\', else: \\\'lib.mainContent\\\')}\')}'}"> + <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"> <p> - <a href="#comments">{f:cObject(typoscriptObjectPath: "lib.sgCommentsGetCountWithLabel")}</a> + <a href="#comments">{f:cObject(typoscriptObjectPath: + "lib.sgCommentsGetCountWithLabel")}</a> <span>//</span> - <f:translate key="frontend.singleview.readingTime" /> + <f:translate key="frontend.singleview.readingTime"/> <strong> - <sg:getReadingTime content="{content}" /> + <sg:getReadingTime content="{content}"/> </strong> </p> @@ -100,7 +113,7 @@ <f:if condition="{newsMetaData.news.newsAuthor -> f:count()}"> <h2> - <f:translate key="frontend.singleview.authors" /> + <f:translate key="frontend.singleview.authors"/> </h2> <hr> @@ -108,7 +121,8 @@ <f:for each="{newsMetaData.news.newsAuthor}" as="newsAuthor" iteration="iterator"> <div id="author{newsAuthor.uid}" class="tx-sgnews-author"> <f:if condition="{newsAuthor.image}"> - <f:image class="tx-sgnews-author-image" image="{newsAuthor.image}" width="150c" height="150px" /> + <f:image class="tx-sgnews-author-image" image="{newsAuthor.image}" width="150c" + height="150px"/> </f:if> <div class="tx-sgnews-author-information"> @@ -122,7 +136,8 @@ <div class="tx-sgnews-author-information-bar"> <f:if condition="{newsAuthor.email}"> <div class="tx-sgnews-author-information-email"> - <span class="glyphicon glyphicon-envelope" aria-hidden="true"></span> + <span class="glyphicon glyphicon-envelope" + aria-hidden="true"></span> <f:link.email email="{newsAuthor.email}" target="_blank"> {newsAuthor.email} </f:link.email> @@ -131,7 +146,8 @@ <f:if condition="{newsAuthor.website}"> <div class="tx-sgnews-author-information-website"> - <span class="glyphicon glyphicon-home" aria-hidden="true"></span> + <span class="glyphicon glyphicon-home" + aria-hidden="true"></span> <f:link.external uri="{newsAuthor.website}" target="_blank"> {newsAuthor.website} </f:link.external> @@ -149,8 +165,10 @@ <f:if condition="{settings.authorNewsPid}"> <div class="tx-sgnews-author-information-articles"> <span class="glyphicon glyphicon-tag" aria-hidden="true"></span> - <f:link.action pageUid="{settings.authorNewsPid}" pluginName="NewsByAuthor" controller="NewsByAuthor" action="list" arguments="{authorId: newsAuthor.uid}"> - <f:translate key="frontend.singleview.authorsAdditionalArticles" /> + <f:link.action pageUid="{settings.authorNewsPid}" + pluginName="NewsByAuthor" controller="NewsByAuthor" + action="list" arguments="{authorId: newsAuthor.uid}"> + <f:translate key="frontend.singleview.authorsAdditionalArticles"/> </f:link.action> </div> </f:if> @@ -165,15 +183,16 @@ <hr> <div class="tx-sgnews-meta-bar"> - <base:sharer /> + <base:sharer/> <div class="tx-sgnews-likes" id="tx-sgnews-likes" data-uid="{newsMetaData.news.uid}"> - <button class="tx-sgnews-like-buton btn btn-sm btn-info" data-ajaxurl="{sgajax:uri.ajax(extensionName: 'SgNews', controller: 'Ajax\Like', action: 'addLike', format: 'json')}"> + <button class="tx-sgnews-like-buton btn btn-sm btn-info" + data-ajaxurl="{sgajax:uri.ajax(extensionName: 'SgNews', controller: 'Ajax\Like', action: 'addLike', format: 'json')}"> <span class="tx-sgnews-number-of-likes"> <span class="badge"><i class="fa fa-star-o" aria-hidden="true"></i> <span class="tx-sgnews-number-of-likes-value">{newsMetaData.news.likes}</span> </span> </span> - <f:translate key="frontend.singleview.likeButton" /> + <f:translate key="frontend.singleview.likeButton"/> </button> </div> </div> @@ -182,7 +201,7 @@ <f:then> <div class="tx-sgnews-single-related"> <h3> - <f:translate key="frontend.singleview.relatedArticles" /> + <f:translate key="frontend.singleview.relatedArticles"/> </h3> <ul> @@ -199,7 +218,7 @@ <f:else> <div class="tx-sgnews-single-related"> <h3> - <f:translate key="frontend.singleview.relatedArticles" /> + <f:translate key="frontend.singleview.relatedArticles"/> </h3> <ul> @@ -225,16 +244,24 @@ <f:if condition="{previousNews} || {nextNews}"> <div class="tx-sgnews-single-footer-browser"> <f:if condition="{previousNews}"> - <a href="{f:uri.page(pageUid: '{previousNews.uid}')}" class="btn btn-md btn-info tx-sgnews-footer-browser-previous"> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#FFF" d="M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zM142.1 273l135.5 135.5c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L226.9 256l101.6-101.6c9.4-9.4 9.4-24.6 0-33.9l-17-17c-9.4-9.4-24.6-9.4-33.9 0L142.1 239c-9.4 9.4-9.4 24.6 0 34z" /></svg> - <f:translate key="frontend.singleview.previousArticle" /> + <a href="{f:uri.page(pageUid: '{previousNews.uid}')}" + class="btn btn-md btn-info tx-sgnews-footer-browser-previous"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> + <path fill="#FFF" + d="M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zM142.1 273l135.5 135.5c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L226.9 256l101.6-101.6c9.4-9.4 9.4-24.6 0-33.9l-17-17c-9.4-9.4-24.6-9.4-33.9 0L142.1 239c-9.4 9.4-9.4 24.6 0 34z"/> + </svg> + <f:translate key="frontend.singleview.previousArticle"/> </a> </f:if> <f:if condition="{nextNews}"> - <a href="{f:uri.page(pageUid: '{nextNews.uid}')}" class="btn btn-md btn-info tx-sgnews-footer-browser-next"> - <f:translate key="frontend.singleview.nextArticle" /> - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#FFF" d="M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zm113.9 231L234.4 103.5c-9.4-9.4-24.6-9.4-33.9 0l-17 17c-9.4 9.4-9.4 24.6 0 33.9L285.1 256 183.5 357.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L369.9 273c9.4-9.4 9.4-24.6 0-34z" /></svg> + <a href="{f:uri.page(pageUid: '{nextNews.uid}')}" + class="btn btn-md btn-info tx-sgnews-footer-browser-next"> + <f:translate key="frontend.singleview.nextArticle"/> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"> + <path fill="#FFF" + d="M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zm113.9 231L234.4 103.5c-9.4-9.4-24.6-9.4-33.9 0l-17 17c-9.4 9.4-9.4 24.6 0 33.9L285.1 256 183.5 357.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L369.9 273c9.4-9.4 9.4-24.6 0-34z"/> + </svg> </a> </f:if> </div> @@ -248,7 +275,7 @@ <div class="container"> <div class="tx-sgnews-single-comments"> <div id="comments" class="tx-sgnews-comments-inner"> - <f:cObject typoscriptObjectPath="lib.sgCommentsIndex" /> + <f:cObject typoscriptObjectPath="lib.sgCommentsIndex"/> </div> </div> </div> -- GitLab