330 lines
11 KiB
PHP
330 lines
11 KiB
PHP
<?php
|
|
|
|
namespace GeorgRinger\News\ViewHelpers;
|
|
|
|
use GeorgRinger\News\Domain\Model\News;
|
|
use GeorgRinger\News\Service\SettingsService;
|
|
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
|
/**
|
|
* This file is part of the "news" Extension for TYPO3 CMS.
|
|
*
|
|
* For the full copyright and license information, please read the
|
|
* LICENSE.txt file that was distributed with this source code.
|
|
*/
|
|
|
|
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
|
|
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;
|
|
|
|
/**
|
|
* ViewHelper to render links from news records to detail view or page
|
|
*
|
|
* # Example: Basic link
|
|
* <code>
|
|
* <n:link newsItem="{newsItem}" settings="{settings}">
|
|
* {newsItem.title}
|
|
* </n:link>
|
|
* </code>
|
|
* <output>
|
|
* A link to the given news record using the news title as link text
|
|
* </output>
|
|
*
|
|
* # Example: Set an additional attribute
|
|
* # Description: Available: class, dir, id, lang, style, title, accesskey, tabindex, onclick
|
|
* <code>
|
|
* <n:link newsItem="{newsItem}" settings="{settings}" class="a-link-class">fo</n:link>
|
|
* </code>
|
|
* <output>
|
|
* <a href="link" class="a-link-class">fo</n:link>
|
|
* </output>
|
|
*
|
|
* # Example: Return the link only
|
|
* <code>
|
|
* <n:link newsItem="{newsItem}" settings="{settings}" uriOnly="1" />
|
|
* </code>
|
|
* <output>
|
|
* The uri is returned
|
|
* </output>
|
|
*/
|
|
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);
|
|
}
|
|
}
|