Search code examples
typo3typo3-8.xtx-news

Internal Link News: excludeAlreadyDisplayedNews


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 :)


Solution

  • This is the complete solution:

    1. write a DataProcessor to get the related news record
    2. add a NewsDataProcessor
    3. add n:excludeDisplayedNews to Fluid Template

    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>