* * {newsItem.title} * * * * A link to the given news record using the news title as link text * * * # Example: Set an additional attribute * # Description: Available: class, dir, id, lang, style, title, accesskey, tabindex, onclick * * fo * * * fo * * * # Example: Return the link only * * * * * The uri is returned * */ class LinkViewHelper extends AbstractTagBasedViewHelper { /** * @var string */ protected $tagName = 'a'; /** * @var \GeorgRinger\News\Service\SettingsService */ protected $pluginSettingsService; /** * @var array */ protected $detailPidDeterminationCallbacks = [ 'flexform' => 'getDetailPidFromFlexform', 'categories' => 'getDetailPidFromCategories', 'default' => 'getDetailPidFromDefaultDetailPid', ]; /** @var ContentObjectRenderer */ protected $cObj; /** * @param \GeorgRinger\News\Service\SettingsService $pluginSettingsService * * @return void */ public function injectSettingsService(SettingsService $pluginSettingsService): void { $this->pluginSettingsService = $pluginSettingsService; } public function initializeArguments() { parent::initializeArguments(); $this->registerUniversalTagAttributes(); $this->registerArgument('newsItem', News::class, 'news item', true); $this->registerArgument('settings', 'array', 'Settings', false, []); $this->registerArgument('uriOnly', 'bool', 'url only', false, false); $this->registerArgument('configuration', 'array', 'configuration', false, []); $this->registerArgument('content', 'string', 'content', false, ''); $this->registerArgument('section', 'string', 'Anchor for links', false); } /** * Render link to news item or internal/external pages * * @return null|string link */ public function render(): ?string { /** @var News $newsItem */ $newsItem = $this->arguments['newsItem']; $settings = $this->arguments['settings'] ?? []; $uriOnly = $this->arguments['uriOnly'] ?? false; $configuration = $this->arguments['configuration'] ?? []; $content = $this->arguments['content'] ?? ''; $tsSettings = (array)$this->pluginSettingsService->getSettings(); ArrayUtility::mergeRecursiveWithOverrule($tsSettings, (array)$settings); // Options with stdWrap enabled won't override $tsSettings as intended here: override them explicit. if (isset($settings['useStdWrap']) && $settings['useStdWrap']) { foreach (GeneralUtility::trimExplode(',', $settings['useStdWrap'], true) as $stdWrapProperty) { if (is_array($tsSettings[$stdWrapProperty]) && array_key_exists($stdWrapProperty, $settings)) { $tsSettings[$stdWrapProperty] = $settings[$stdWrapProperty]; } } } $this->init(); $linkedContent = $this->renderChildren(); if ($newsItem === null) { return $linkedContent; } $newsType = (int)$newsItem->getType(); switch ($newsType) { // internal news case 1: $configuration['parameter'] = $newsItem->getInternalurl(); break; // external news case 2: $configuration['parameter'] = $newsItem->getExternalurl(); break; // normal news record default: $configuration = $this->getLinkToNewsItem($newsItem, $tsSettings, $configuration); } $url = $this->cObj->typoLink_URL($configuration); // link could not be generated if ($url === '' || $linkedContent === $url) { return $linkedContent; } if ($this->hasArgument('section')) { $url .= '#' . $this->arguments['section']; } if ($uriOnly) { return $url; } if (isset($tsSettings['link']['typesOpeningInNewWindow'])) { if (GeneralUtility::inList($tsSettings['link']['typesOpeningInNewWindow'], $newsType)) { $this->tag->addAttribute('target', '_blank'); } } if (!$this->tag->hasAttribute('target')) { $target = $this->getTargetConfiguration($configuration); if (!empty($target)) { $this->tag->addAttribute('target', $target); } } $this->tag->addAttribute('href', $url); if (empty($content)) { $content = $linkedContent; } $this->tag->setContent($content); return $this->tag->render(); } /** * Generate the link configuration for the link to the news item * * @param News $newsItem * @param array $tsSettings * @param array $configuration * @return array */ protected function getLinkToNewsItem( News $newsItem, $tsSettings, array $configuration = [] ): array { if (!isset($configuration['parameter'])) { $detailPid = 0; // if TS is not set, prefer flexform setting if (!isset($tsSettings['detailPidDetermination'])) { $detailPidDeterminationMethods = ['flexform']; } else { $detailPidDeterminationMethods = GeneralUtility::trimExplode( ',', $tsSettings['detailPidDetermination'], true ); } foreach ($detailPidDeterminationMethods as $determinationMethod) { if ($callback = $this->detailPidDeterminationCallbacks[$determinationMethod]) { if ($detailPid = call_user_func([$this, $callback], $tsSettings, $newsItem)) { break; } } } if (!$detailPid && isset($GLOBALS['TSFE'])) { $detailPid = $GLOBALS['TSFE']->id; } $configuration['parameter'] = $detailPid; } $configuration['additionalParams'] = (isset($configuration['additionalParams']) ? $configuration['additionalParams'] : '') . '&tx_news_pi1[news]=' . $this->getNewsId($newsItem); $configuration['additionalParams'] .= '&tx_news_pi1[controller]=News&tx_news_pi1[action]=detail'; // Add date as human readable if (isset($tsSettings['link']['hrDate']) && $tsSettings['link']['hrDate'] == 1 || isset($tsSettings['link']['hrDate']['_typoScriptNodeValue']) && $tsSettings['link']['hrDate']['_typoScriptNodeValue'] == 1) { $dateTime = $newsItem->getDatetime(); if (!is_null($dateTime)) { if (!empty($tsSettings['link']['hrDate']['day'])) { $configuration['additionalParams'] .= '&tx_news_pi1[day]=' . $dateTime->format($tsSettings['link']['hrDate']['day']); } if (!empty($tsSettings['link']['hrDate']['month'])) { $configuration['additionalParams'] .= '&tx_news_pi1[month]=' . $dateTime->format($tsSettings['link']['hrDate']['month']); } if (!empty($tsSettings['link']['hrDate']['year'])) { $configuration['additionalParams'] .= '&tx_news_pi1[year]=' . $dateTime->format($tsSettings['link']['hrDate']['year']); } } } return $configuration; } /** * @param News $newsItem * @return int */ protected function getNewsId(News $newsItem): int { $uid = $newsItem->getUid(); // If a user is logged in and not in live workspace if (isset($GLOBALS['BE_USER']) && $GLOBALS['BE_USER']->workspace > 0) { $record = BackendUtility::getLiveVersionOfRecord( 'tx_news_domain_model_news', $newsItem->getUid() ); if ($record['uid']) { $uid = $record['uid']; } } return $uid; } /** * @param array $configuration * @return string */ protected function getTargetConfiguration(array $configuration): string { $configuration['returnLast'] = 'target'; return $this->cObj->typoLink('dummy', $configuration); } /** * Gets detailPid from categories of the given news item. First will be return. * * @param array $settings * @param News $newsItem * @return int */ protected function getDetailPidFromCategories($settings, $newsItem): int { $detailPid = 0; if ($newsItem->getCategories()) { foreach ($newsItem->getCategories() as $category) { if ($detailPid = (int)$category->getSinglePid()) { break; } } } return $detailPid; } /** * Gets detailPid from defaultDetailPid setting * * @param array $settings * @param News $newsItem * @return int */ protected function getDetailPidFromDefaultDetailPid($settings, $newsItem): int { return isset($settings['defaultDetailPid']) ? (int)$settings['defaultDetailPid'] : 0; } /** * Gets detailPid from flexform of current plugin. * * @param array $settings * @param News $newsItem * @return int */ protected function getDetailPidFromFlexform($settings, $newsItem): int { return isset($settings['detailPid']) ? (int)$settings['detailPid'] : 0; } /** * Initialize properties * * @return void */ protected function init(): void { $this->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class); } }