Reputation: 670
I am using internal link news, this means I am using standard pages as news pages. On these pages I have a news slider to display other news. Here I need the option: excludeAlreadyDisplayedNews to remove the current page from news.
But how to add <n:excludeDisplayedNews newsItem="{newsItem}"/>
on standard pages?
Is there a typoscript for loading the related newsItem for this page? Maybe a dataprocesser could do the trick, but I do not know how?
Another idea was adding an additional field to pages, so the user adds the news record to the page. This is one click more, OK, but when passing the news UID to the viewhelper, I get this error message:
The argument "newsItem" was registered with type "GeorgRinger\News\Domain\Model\News", but is of type "integer" in view helper "GeorgRinger\News\ViewHelpers\ExcludeDisplayedNewsViewHelper".
Any help appreciated :)
Upvotes: 0
Views: 961
Reputation: 670
This is the complete solution:
Step 1: in your Page Typoscript, add a DataProcessor to get the related news record. Add this to the dataProcession block of your page FLUIDTEMPLATE Typoscript:
10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
10 {
table = tx_news_domain_model_news
#pid for news folder
pidInList = 123
where.data = page : uid
where.wrap = internalurl=|
as = displayedNews
dataProcessing {
10 = MyCompany\MyExtension\DataProcessor\NewsDataProcessor
10 {
field = uid
}
}
}
Attention: internalUrl is a string. For me it worked like this, but there might be typolink syntax required. Any query improvements welcome!
Step 2: Add a NewsDataProcessor in MyExtension/Classes/DataProcessor/NewsDataProcessor.php
<?php
namespace MyCompany\MyExtension\DataProcessor;
use GeorgRinger\News\Domain\Repository\NewsRepository;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;
class NewsDataProcessor implements DataProcessorInterface
{
/**
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $cObj
* @param array $contentObjectConfiguration
* @param array $processorConfiguration
* @param array $processedData
* @return array
*/
public function process(
ContentObjectRenderer $cObj,
array $contentObjectConfiguration,
array $processorConfiguration,
array $processedData
) {
/** @var \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager */
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
/** @var \GeorgRinger\News\Domain\Repository\NewsRepository $newsRepository */
$newsRepository = $objectManager->get(NewsRepository::class);
$field = 'uid';
if (array_key_exists('field',$processorConfiguration)) {
$field = $processorConfiguration['field'];
}
$newsArray = $processedData['data'];
$news = $newsRepository->findByUid((int)$newsArray[$field], false);
$processedData['news'] = $news;
return $processedData;
}
}
In later EXT:news versions (currently 7.0.7) there might be a DataProcessor available, then you can skip this step and use the existing one
Step 3: Add the n:excludeDisplayedNews Viewhelper to the Fluid Template of your page. Don't forget to add the Viewhelper namespace to the template.
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:n="http://typo3.org/ns/GeorgRinger/News/ViewHelpers"
data-namespace-typo3-fluid="true">
<f:layout name="MyLayout"/>
<f:section name="main">
<f:for each="{displayedNews}" as="newsItem">
<n:excludeDisplayedNews newsItem="{newsItem.news}" />
</f:for>
<div class="main-content">
...
</div>
</f:section>
</html>
Upvotes: 1
Reputation: 4565
I don't think there is a simple, clean way to do this. The page isn't the actual news records, so technically it's not displayed. I can think of 3 possible solutions:
Actually technically display the news record on the page, with an empty template (except for the n:excludeDisplayedNews
ViewHelper) so it doesn't show anything. I'm not sure if this will work with "internal link" news items though, but if it does this is the easiest way.
You can do this using the following TypoScript:
lib.displayedNews = USER
lib.displayedNews {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
extensionName = News
pluginName = Pi1
vendorName = GeorgRinger
switchableControllerActions {
News {
1 = detail
}
}
views =< plugin.tx_news.view
view {
templateRootPaths.200 = path/to/template/with/only/excludeDisplayedNews/
}
settings =< plugin.tx_news.settings
settings {
singleNews.current = 1
useStdWrap = singleNews
insertRecord = 1
}
}
In your page template you can use:
<f:for each="{displayedNews}" as="newsItem">
<f:cObject typoscriptObjectPath="lib.displayedNews" data="{newsItem.data.uid}" />
</f:for>
And your News/Detail.html
template would just be:
<n:excludeDisplayedNews newsItem="{newsItem.uid}" />
Fetch the news record object with a custom ViewHelper or DataProcessor so you can fill it into the n:excludeDisplayedNews
ViewHelper. In my opinion this is the cleanest solution, but also requires the most work.
Make a user function to fill the global array the news extension uses to keep track of the displayed news records, like: $GLOBALS['EXT']['news']['alreadyDisplayed'][$newsUid] = $newsUid;
Upvotes: 1