Initial commit - Typo3 11.5.41

This commit is contained in:
Matteo Gallo
2026-07-03 17:53:31 +02:00
commit 5ca4743197
6811 changed files with 568848 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
<?php
namespace GeorgRinger\News\Hooks\Backend;
/**
* 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\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Hook into PageLayoutView to hide tt_content elements in page view
*/
class PageViewQueryHook
{
protected static $count = 0;
/**
* Prevent inline tt_content elements in news articles from
* showing in the page module.
*
* @param array $parameters
* @param string $table
* @param int $pageId
* @param array $additionalConstraints
* @param string[] $fieldList
* @param QueryBuilder $queryBuilder
*/
public function modifyQuery(
$parameters,
$table,
$pageId,
$additionalConstraints,
$fieldList,
QueryBuilder $queryBuilder
): void {
if ($table === 'tt_content' && $pageId > 0) {
// Get page record base on page uid
$pageRecord = BackendUtility::getRecord('pages', $pageId, 'uid', " AND doktype='254' AND module='news'");
if (is_array($pageRecord)) {
$tsConfig = BackendUtility::getPagesTSconfig($pageId);
if ((int)($tsConfig['tx_news.']['showContentElementsInNewsSysFolder'] ?? 0) === 1) {
return;
}
// Only hide elements which are inline, allowing for standard
// elements to show
$queryBuilder->andWhere(
$queryBuilder->expr()->eq('tx_news_related_news', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
);
if (self::$count === 0) {
$this->addFlashMessage();
}
self::$count++;
}
}
}
/**
* Render flash message to inform user
* that no elements belonging to news articles
* are rendered in the page module
*
* @return void
*/
private function addFlashMessage(): void
{
$message = GeneralUtility::makeInstance(
FlashMessage::class,
$this->getLanguageService()->sL('LLL:EXT:news/Resources/Private/Language/locallang_be.xlf:hiddenContentElements.description'),
'',
FlashMessage::INFO
);
$flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
$defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
$defaultFlashMessageQueue->enqueue($message);
}
/**
* @return LanguageService
*/
protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
}

View File

@@ -0,0 +1,102 @@
<?php
namespace GeorgRinger\News\Hooks\Backend;
/**
* 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 GeorgRinger\News\Backend\RecordList\RecordListConstraint;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Hook into DatabaseRecordList to hide tt_content elements in list view
*/
class RecordListQueryHook
{
protected static $count = 0;
/** @var RecordListConstraint */
protected $recordListConstraint;
/**
* RecordListQueryHook constructor.
* @param RecordListConstraint $recordListConstraint
*/
public function __construct(
RecordListConstraint $recordListConstraint
) {
$this->recordListConstraint = $recordListConstraint;
}
/**
* @return void
*/
public function modifyQuery(
array &$parameters,
string $table,
int $pageId,
array $additionalConstraints,
array $fieldList,
QueryBuilder $queryBuilder
) {
if ($table === 'tt_content' && $pageId > 0) {
$pageRecord = BackendUtility::getRecord('pages', $pageId, 'uid', " AND doktype='254' AND module='news'");
if (is_array($pageRecord)) {
$tsConfig = BackendUtility::getPagesTSconfig($pageId);
if ((int)($tsConfig['tx_news.']['showContentElementsInNewsSysFolder'] ?? 0) === 1) {
return;
}
$queryBuilder->where(...['1=2']);
if (self::$count === 0) {
$this->addFlashMessage();
}
self::$count++;
}
} elseif ($table === 'tx_news_domain_model_news' && $this->recordListConstraint->isInAdministrationModule()) {
$vars = GeneralUtility::_GET('tx_news_web_newsadministration');
if (is_array($vars) && is_array($vars['demand'])) {
$vars = $vars['demand'];
$this->recordListConstraint->extendQuery($parameters, $vars);
if (isset($parameters['orderBy'][0])) {
$queryBuilder->orderBy($parameters['orderBy'][0][0], $parameters['orderBy'][0][1]);
unset($parameters['orderBy']);
}
if (!empty($parameters['whereDoctrine'])) {
$queryBuilder->andWhere(...$parameters['whereDoctrine']);
unset($parameters['where']);
}
}
}
}
private function addFlashMessage(): void
{
$message = GeneralUtility::makeInstance(
FlashMessage::class,
$this->getLanguageService()->sL('LLL:EXT:news/Resources/Private/Language/locallang_be.xlf:hiddenContentElements.description'),
'',
FlashMessage::INFO
);
$flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
$defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
$defaultFlashMessageQueue->enqueue($message);
}
/**
* @return LanguageService
*/
protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}
}

View File

@@ -0,0 +1,291 @@
<?php
namespace GeorgRinger\News\Hooks;
/**
* 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 GeorgRinger\News\Domain\Model\Dto\EmConfiguration;
use TYPO3\CMS\Backend\Utility\BackendUtility as BackendUtilityCore;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Hook into \TYPO3\CMS\Backend\Utility\BackendUtility to change flexform behaviour
* depending on action selection
*/
class BackendUtility
{
/**
* Fields which are removed in detail view
*
* @var array
*/
public $removedFieldsInDetailView = [
'sDEF' => 'orderBy,orderDirection,categories,categoryConjunction,includeSubCategories,
archiveRestriction,timeRestriction,timeRestrictionHigh,topNewsRestriction,
dateField,selectedList',
'additional' => 'limit,offset,hidePagination,topNewsFirst,listPid,list.paginate.itemsPerPage',
'template' => 'cropMaxCharacters'
];
/**
* Fields which are removed in list view
*
* @var array
*/
public $removedFieldsInListView = [
'sDEF' => 'dateField,singleNews,previewHiddenRecords,selectedList',
'additional' => '',
'template' => ''
];
/**
* Fields which are removed in selected list view
*
* @var array
*/
public $removedFieldsInSelectedListView = [
'sDEF' => 'categories,categoryConjunction,includeSubCategories,
archiveRestriction,timeRestriction,timeRestrictionHigh,topNewsRestriction,
startingpoint,recursive,dateField,singleNews,previewHiddenRecords,
previewHiddenRecords,startingpoint,recursive',
'additional' => 'tags,limit,offset,hidePagination,topNewsFirst,backPid,excludeAlreadyDisplayedNews,
list.paginate.itemsPerPage,disableOverrideDemand',
'template' => ''
];
/**
* Fields which are removed in dateMenu view
*
* @var array
*/
public $removedFieldsInDateMenuView = [
'sDEF' => 'orderBy,singleNews,selectedList',
'additional' => 'limit,offset,hidePagination,topNewsFirst,backPid,previewHiddenRecords,excludeAlreadyDisplayedNews,
list.paginate.itemsPerPage',
'template' => 'cropMaxCharacters,media.maxWidth,media.maxHeight'
];
/**
* Fields which are removed in search form view
*
* @var array
*/
public $removedFieldsInSearchFormView = [
'sDEF' => 'orderBy,orderDirection,categories,categoryConjunction,includeSubCategories,
archiveRestriction,timeRestriction,timeRestrictionHigh,topNewsRestriction,
startingpoint,recursive,dateField,singleNews,previewHiddenRecords,selectedList',
'additional' => 'limit,offset,hidePagination,topNewsFirst,detailPid,backPid,excludeAlreadyDisplayedNews,
list.paginate.itemsPerPage',
'template' => 'cropMaxCharacters,media.maxWidth,media.maxHeight'
];
/**
* Fields which are removed in category list view
*
* @var array
*/
public $removedFieldsInCategoryListView = [
'sDEF' => 'orderBy,orderDirection,categoryConjunction,includeSubCategories,
archiveRestriction,timeRestriction,timeRestrictionHigh,topNewsRestriction,
recursive,dateField,singleNews,previewHiddenRecords,selectedList',
'additional' => 'limit,offset,hidePagination,topNewsFirst,detailPid,backPid,excludeAlreadyDisplayedNews,
list.paginate.itemsPerPage',
'template' => 'cropMaxCharacters,media.maxWidth,media.maxHeight'
];
/**
* Fields which are removed in tag list view
*
* @var array
*/
public $removedFieldsInTagListView = [
'sDEF' => 'categories,categoryConjunction,includeSubCategories,
archiveRestriction,timeRestriction,timeRestrictionHigh,topNewsRestriction,
dateField,singleNews,previewHiddenRecords,selectedList',
'additional' => 'limit,offset,hidePagination,topNewsFirst,detailPid,backPid,excludeAlreadyDisplayedNews,
list.paginate.itemsPerPage',
'template' => 'cropMaxCharacters,media.maxWidth,media.maxHeight'
];
/** @var EmConfiguration */
protected $configuration;
/**
* BackendUtility constructor.
* @param EmConfiguration $configuration
*/
public function __construct(
) {
$this->configuration = GeneralUtility::makeInstance(EmConfiguration::class);
}
/**
* @param array $dataStructure
* @param array $identifier
*
* @return array|string
*/
public function parseDataStructureByIdentifierPostProcess(array $dataStructure, array $identifier)
{
if ($identifier['type'] === 'tca' && $identifier['tableName'] === 'tt_content' && $identifier['dataStructureKey'] === 'news_pi1,list') {
$getVars = GeneralUtility::_GET('edit');
if (isset($getVars['tt_content']) && is_array($getVars['tt_content'])) {
$item = array_keys($getVars['tt_content']);
$recordId = (int)$item[0];
if (($getVars['tt_content'][$recordId] ?? '') === 'new') {
$fakeRow = [
'uid' => 'NEW123'
];
$this->updateFlexforms($dataStructure, $fakeRow);
} else {
$row = BackendUtilityCore::getRecord('tt_content', $recordId);
if (is_array($row)) {
$this->updateFlexforms($dataStructure, $row);
}
}
}
}
return $dataStructure;
}
/**
* Update flexform configuration if a action is selected
*
* @param array|string &$dataStructure flexform structure
* @param array $row row of current record
* @param array $dataStructure
*
* @return void
*/
protected function updateFlexforms(array &$dataStructure, array $row): void
{
$selectedView = '';
$flexformSelection = [];
if (isset($row['pi_flexform'])) {
// get the first selected action
if (is_string($row['pi_flexform'])) {
$flexformSelection = GeneralUtility::xml2array($row['pi_flexform']);
} else {
$flexformSelection = $row['pi_flexform'];
}
}
if (is_array($flexformSelection) && isset($flexformSelection['data'])) {
$selectedView = $flexformSelection['data']['sDEF']['lDEF']['switchableControllerActions']['vDEF'] ?? '';
if (!empty($selectedView)) {
$actionParts = GeneralUtility::trimExplode(';', $selectedView, true);
$selectedView = $actionParts[0];
}
// new plugin element
} elseif (str_starts_with((string)$row['uid'], 'NEW')) {
// use List as starting view
$selectedView = 'News->list';
}
if (!empty($selectedView)) {
// Modify the flexform structure depending on the first found action
switch ($selectedView) {
case 'News->list':
case 'News->searchResult':
$this->deleteFromStructure($dataStructure, $this->removedFieldsInListView);
break;
case 'News->detail':
$this->deleteFromStructure($dataStructure, $this->removedFieldsInDetailView);
break;
case 'News->selectedList':
$this->deleteFromStructure($dataStructure, $this->removedFieldsInSelectedListView);
break;
case 'News->searchForm':
$this->deleteFromStructure($dataStructure, $this->removedFieldsInSearchFormView);
break;
case 'News->dateMenu':
$this->deleteFromStructure($dataStructure, $this->removedFieldsInDateMenuView);
break;
case 'Category->list':
$this->deleteFromStructure($dataStructure, $this->removedFieldsInCategoryListView);
break;
case 'Tag->list':
$this->deleteFromStructure($dataStructure, $this->removedFieldsInTagListView);
break;
default:
}
if ($GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['Hooks/BackendUtility.php']['updateFlexforms'] ?? []) {
$params = [
'selectedView' => $selectedView,
'dataStructure' => &$dataStructure,
];
foreach ($GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['Hooks/BackendUtility.php']['updateFlexforms'] as $reference) {
GeneralUtility::callUserFunction($reference, $params, $this);
}
}
}
}
/**
* Add category restriction to flexforms
*
* @param array $structure
*
* @return void
*/
protected function addCategoryConstraints(&$structure): void
{
$categoryRestrictionSetting = $this->configuration->getCategoryRestriction();
$categoryRestriction = '';
switch ($categoryRestrictionSetting) {
case 'current_pid':
$categoryRestriction = ' AND sys_category.pid=###CURRENT_PID### ';
break;
case 'siteroot':
$categoryRestriction = ' AND sys_category.pid IN (###SITEROOT###) ';
break;
case 'page_tsconfig':
$categoryRestriction = ' AND sys_category.pid IN (###PAGE_TSCONFIG_IDLIST###) ';
break;
}
if (!empty($categoryRestriction) && isset($structure['sheets']['sDEF']['ROOT']['el']['settings.categories'])) {
$structure['sheets']['sDEF']['ROOT']['el']['settings.categories']['TCEforms']['config']['foreign_table_where'] = $categoryRestriction . $structure['sheets']['sDEF']['ROOT']['el']['settings.categories']['TCEforms']['config']['foreign_table_where'];
}
}
/**
* Remove fields from flexform structure
*
* @param array &$dataStructure flexform structure
* @param array $fieldsToBeRemoved fields which need to be removed
*
* @return void
*/
protected function deleteFromStructure(array &$dataStructure, array $fieldsToBeRemoved): void
{
foreach ($fieldsToBeRemoved as $sheetName => $sheetFields) {
$fieldsInSheet = GeneralUtility::trimExplode(',', $sheetFields, true);
foreach ($fieldsInSheet as $fieldName) {
unset($dataStructure['sheets'][$sheetName]['ROOT']['el']['settings.' . $fieldName]);
}
}
}
/**
* @param int $pageId
* @return bool
*/
protected function enabledInTsConfig($pageId): bool
{
$tsConfig = BackendUtilityCore::getPagesTSconfig($pageId);
if (isset($tsConfig['tx_news.']['categoryRestrictionForFlexForms'])) {
return (bool)$tsConfig['tx_news.']['categoryRestrictionForFlexForms'];
}
return false;
}
}

View File

@@ -0,0 +1,183 @@
<?php
namespace GeorgRinger\News\Hooks;
/**
* 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 GeorgRinger\News\Service\AccessControlService;
use TYPO3\CMS\Backend\Utility\BackendUtility as BackendUtilityCore;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Hook into tcemain which is used to show preview of news item
*/
class DataHandler implements SingletonInterface
{
protected $cacheTagsToFlush = [];
/**
* Flushes the cache if a news record was edited.
* This happens on two levels: by UID and by PID.
*
* @param array $params
*
* @return void
*/
public function clearCachePostProc(array $params): void
{
if (isset($params['table']) && $params['table'] === 'tx_news_domain_model_news') {
if (isset($params['uid'])) {
$this->cacheTagsToFlush[] = 'tx_news_uid_' . $params['uid'];
}
if (isset($params['uid_page'])) {
$this->cacheTagsToFlush[] = 'tx_news_pid_' . $params['uid_page'];
}
$cacheManager = GeneralUtility::makeInstance(CacheManager::class);
foreach (array_unique($this->cacheTagsToFlush) as $cacheTag) {
$cacheManager->flushCachesInGroupByTag('pages', $cacheTag);
}
}
}
/**
* Generate a different preview link *
*
* @param string $status status
* @param string $table table name
* @param int $recordUid id of the record
* @param array $fields fieldArray
* @param \TYPO3\CMS\Core\DataHandling\DataHandler $parentObject parent Object
*
* @return void
*/
public function processDatamap_afterDatabaseOperations(
$status,
$table,
$recordUid,
array $fields,
\TYPO3\CMS\Core\DataHandling\DataHandler $parentObject
): void {
// Clear category cache
if ($table === 'sys_category') {
$cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('news_category');
$cache->flush();
}
}
/**
* Prevent saving of a news record if the editor doesn't have access to all categories of the news record
*
* @param array $fieldArray
* @param string $table
* @param int $id
* @param $parentObject \TYPO3\CMS\Core\DataHandling\DataHandler
*
* @return void
*/
public function processDatamap_preProcessFieldArray(&$fieldArray, $table, $id, $parentObject): void
{
if ($table === 'tx_news_domain_model_news') {
// check permissions of assigned categories
if (is_int($id) && !$this->getBackendUser()->isAdmin()) {
$newsRecord = BackendUtilityCore::getRecord($table, $id);
if (!AccessControlService::userHasCategoryPermissionsForRecord($newsRecord)) {
$parentObject->log(
$table,
$id,
2,
0,
1,
"processDatamap: Attempt to modify a record from table '%s' without permission. Reason: the record has one or more categories assigned that are not defined in your BE usergroup.",
1,
[$table]
);
// unset fieldArray to prevent saving of the record
$fieldArray = [];
} else {
// If the category relation has been modified, no | is found anymore
if (isset($fieldArray['categories']) && strpos($fieldArray['categories'], '|') === false) {
$deniedCategories = AccessControlService::getAccessDeniedCategories($newsRecord);
if (is_array($deniedCategories)) {
foreach ($deniedCategories as $deniedCategory) {
$fieldArray['categories'] .= ',' . $deniedCategory['uid'];
}
// Check if the categories are not empty,
if (!empty($fieldArray['categories'])) {
$fieldArray['categories'] = trim($fieldArray['categories'], ',');
}
}
}
}
}
}
}
/**
* Prevent deleting/moving of a news record if the editor doesn't have access to all categories of the news record
*
* @param string $command
* @param string $table
* @param int $id
* @param string $value
* @param $parentObject \TYPO3\CMS\Core\DataHandling\DataHandler
*
* @return void
*/
public function processCmdmap_preProcess($command, &$table, $id, $value, $parentObject): void
{
if ($table === 'tx_news_domain_model_news' && !$this->getBackendUser()->isAdmin() && is_int($id) && $command !== 'undelete') {
$newsRecord = BackendUtilityCore::getRecord($table, $id);
if (is_array($newsRecord) && !AccessControlService::userHasCategoryPermissionsForRecord($newsRecord)) {
$parentObject->log(
$table,
$id,
2,
0,
1,
'processCmdmap: Attempt to ' . $command . " a record from table '%s' without permission. Reason: the record has one or more categories assigned that are not defined in the BE usergroup.",
1,
[$table]
);
// unset table to prevent saving
$table = '';
}
}
}
/**
* Flush cache for old news pid when moving record
*
* @param string $table
* @param int $uid
* @param int $destPid
* @param array $propArr
* @param array $moveRec
* @param int $resolvedPid
* @param bool $recordWasMoved
* @param \TYPO3\CMS\Core\DataHandling\DataHandler $dataHandler
*/
public function moveRecord($table, $uid, $destPid, $propArr, $moveRec, $resolvedPid, $recordWasMoved, \TYPO3\CMS\Core\DataHandling\DataHandler $dataHandler)
{
if ($table === 'tx_news_domain_model_news') {
$this->cacheTagsToFlush[] = 'tx_news_pid_' . $moveRec['pid'];
}
}
/**
* Returns the current BE user.
*
* @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
*/
protected function getBackendUser(): \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace GeorgRinger\News\Hooks;
use GeorgRinger\News\Domain\Model\Dto\EmConfiguration;
/**
* 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\Backend\Form\Element\InlineElement;
use TYPO3\CMS\Backend\Form\Element\InlineElementHookInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Inline Element Hook
*/
class InlineElementHook implements InlineElementHookInterface
{
/**
* Initializes this hook object.
*
* @param InlineElement $parentObject
*
* @return void
*/
public function init(&$parentObject): void
{
}
/**
* Pre-processing to define which control items are enabled or disabled.
*
* @param string $parentUid The uid of the parent (embedding) record (uid or NEW...)
* @param string $foreignTable The table (foreign_table) we create control-icons for
* @param array $childRecord The current record of that foreign_table
* @param array $childConfig TCA configuration of the current field of the child record
* @param bool $isVirtual Defines whether the current records is only virtually shown and not physically part of the parent record
* @param array &$enabledControls (reference) Associative array with the enabled control items
*
* @return void
*/
public function renderForeignRecordHeaderControl_preProcess(
$parentUid,
$foreignTable,
array $childRecord,
array $childConfig,
$isVirtual,
array &$enabledControls
) {
}
/**
* Post-processing to define which control items to show. Possibly own icons can be added here.
*
* @param string $parentUid The uid of the parent (embedding) record (uid or NEW...)
* @param string $foreignTable The table (foreign_table) we create control-icons for
* @param array $childRecord The current record of that foreign_table
* @param array $childConfig TCA configuration of the current field of the child record
* @param bool $isVirtual Defines whether the current records is only virtually shown and not physically part of the parent record
* @param array &$controlItems (reference) Associative array with the currently available control items
*
* @return void
*/
public function renderForeignRecordHeaderControl_postProcess(
$parentUid,
$foreignTable,
array $childRecord,
array $childConfig,
$isVirtual,
array &$controlItems
) {
$previewSetting = (int)($childRecord['showinpreview'] ?? 0);
if ($foreignTable === 'sys_file_reference' && $previewSetting > 0) {
$ll = 'LLL:EXT:news/Resources/Private/Language/locallang_db.xlf:';
$extensionConfiguration = GeneralUtility::makeInstance(EmConfiguration::class);
if ($extensionConfiguration->isAdvancedMediaPreview()) {
if ($previewSetting === 1) {
$label = $GLOBALS['LANG']->sL($ll . 'tx_news_domain_model_media.showinviews.1');
$extraItem = ['showinpreview' => ' <span class="btn btn-default" title="' . htmlspecialchars($label) . '"><i class="fa fa-check"></i></span>'];
$controlItems = $extraItem + $controlItems;
} elseif ($previewSetting === 2) {
$label = $GLOBALS['LANG']->sL($ll . 'tx_news_domain_model_media.showinviews.2');
$extraItem = ['showinpreview' => ' <span class="btn btn-default" title="' . htmlspecialchars($label) . '"><i class="fa fa-check-square"></i></span>'];
$controlItems = $extraItem + $controlItems;
}
} elseif ($previewSetting === 1) {
$label = $GLOBALS['LANG']->sL($ll . 'tx_news_domain_model_media.showinpreview');
$extraItem = ['showinpreview' => ' <span class="btn btn-default" title="' . htmlspecialchars($label) . '"><i class="fa fa-check"></i></span>'];
$controlItems = $extraItem + $controlItems;
}
}
}
}

View File

@@ -0,0 +1,323 @@
<?php
namespace GeorgRinger\News\Hooks;
/**
* 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 GeorgRinger\News\Utility\TemplateLayout;
use TYPO3\CMS\Backend\Utility\BackendUtility as BackendUtilityCore;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Information\Typo3Version;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Userfunc to render alternative label for media elements
*/
class ItemsProcFunc
{
/** @var TemplateLayout $templateLayoutsUtility */
protected $templateLayoutsUtility;
/**
* ItemsProcFunc constructor.
* @param TemplateLayout $templateLayout
*/
public function __construct(
TemplateLayout $templateLayout
) {
$this->templateLayoutsUtility = $templateLayout;
}
/**
* Itemsproc function to extend the selection of templateLayouts in the plugin
*
* @param array &$config configuration array
*
* @return void
*/
public function user_templateLayout(array &$config): void
{
$pageId = 0;
$currentColPos = $config['flexParentDatabaseRow']['colPos'];
$pageId = $this->getPageId($config['flexParentDatabaseRow']['pid']);
if ($pageId > 0) {
$templateLayouts = $this->templateLayoutsUtility->getAvailableTemplateLayouts($pageId);
$templateLayouts = $this->reduceTemplateLayouts($templateLayouts, $currentColPos);
foreach ($templateLayouts as $layout) {
$additionalLayout = [
htmlspecialchars($this->getLanguageService()->sL($layout[0])),
$layout[1]
];
array_push($config['items'], $additionalLayout);
}
}
}
/**
* Reduce the template layouts by the ones that are not allowed in given colPos
*
* @param array $templateLayouts
* @param int $currentColPos
* @return array
*/
protected function reduceTemplateLayouts($templateLayouts, $currentColPos): array
{
$currentColPos = (int)$currentColPos;
$restrictions = [];
$allLayouts = [];
foreach ($templateLayouts as $key => $layout) {
if (is_array($layout[0])) {
if (isset($layout[0]['allowedColPos']) && str_ends_with((string)$layout[1], '.')) {
$layoutKey = substr($layout[1], 0, -1);
$restrictions[$layoutKey] = GeneralUtility::intExplode(',', $layout[0]['allowedColPos'], true);
}
} else {
$allLayouts[$key] = $layout;
}
}
if (!empty($restrictions)) {
foreach ($restrictions as $restrictedIdentifier => $restrictedColPosList) {
if (!in_array($currentColPos, $restrictedColPosList, true)) {
unset($allLayouts[$restrictedIdentifier]);
}
}
}
return $allLayouts;
}
/**
* Modifies the select box of orderBy-options as a category menu
* needs different ones then a news action
*
* @param array &$config configuration array
*
* @return void
*/
public function user_orderBy(array &$config): void
{
$row = $this->getContentElementRow($config['row']['uid']);
// check if the record has been saved once
if (is_array($row) && !empty($row['pi_flexform'])) {
$flexformConfig = GeneralUtility::xml2array($row['pi_flexform']);
// check if there is a flexform configuration
if (isset($flexformConfig['data']['sDEF']['lDEF']['switchableControllerActions']['vDEF'])) {
$selectedActionList = $flexformConfig['data']['sDEF']['lDEF']['switchableControllerActions']['vDEF'] ?? '';
// check for selected action
if (str_starts_with($selectedActionList, 'Category')) {
$newItems = $GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['orderByCategory'];
} elseif (str_starts_with($selectedActionList, 'Tag')) {
$this->removeNonValidOrderFields($config, 'tx_news_domain_model_tag');
$newItems = $GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['orderByTag'];
} else {
$newItems = $GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['orderByNews'];
}
}
}
// if a override configuration is found
if (!empty($newItems)) {
// remove default configuration
$config['items'] = [];
// empty default line
array_push($config['items'], ['', '']);
$newItemArray = GeneralUtility::trimExplode(',', $newItems, true);
$languageKey = 'LLL:EXT:news/Resources/Private/Language/locallang_be.xlf:flexforms_general.orderBy.';
foreach ($newItemArray as $item) {
// label: if empty, key (=field) is used
$label = $this->getLanguageService()->sL($languageKey . $item);
if (empty($label)) {
$label = $item;
}
array_push($config['items'], [htmlspecialchars($label), $item]);
}
}
}
/**
* Remove not valid fields from ordering
*
* @param array $config tca items
* @param string $tableName table name
*
* @return void
*/
protected function removeNonValidOrderFields(array &$config, $tableName): void
{
$allowedFields = array_keys($GLOBALS['TCA'][$tableName]['columns']);
foreach ($config['items'] as $key => $item) {
if ($item[1] != '' && !in_array($item[1], $allowedFields)) {
unset($config['items'][$key]);
}
}
}
/**
* Modifies the selectbox of available actions
*
* @param array &$config
*
* @return void
*/
public function user_switchableControllerActions(array &$config): void
{
if (!empty($GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['switchableControllerActions']['list'])) {
$configuration = (int)$GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['switchableControllerActions']['list'];
switch ($configuration) {
case 1:
$this->removeActionFromList($config, 'News->list');
break;
case 2:
$this->removeActionFromList($config, 'News->list;News->detail');
break;
default:
}
}
// Add additional actions
if (isset($GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['switchableControllerActions']['newItems'])
&& is_array($GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['switchableControllerActions']['newItems'])
) {
foreach ($GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['switchableControllerActions']['newItems'] as $key => $label) {
array_push($config['items'], [$this->getLanguageService()->sL($label), $key, '']);
}
}
}
/**
* Remove given action from switchableControllerActions
*
* @param array $config available items
* @param string $action action to be removed
*
* @return void
*/
private function removeActionFromList(array &$config, $action): void
{
foreach ($config['items'] as $key => $item) {
if ($item[1] === $action) {
unset($config['items'][$key]);
continue;
}
}
}
/**
* Generate a select box of languages to choose an overlay
*
* @return string select box
*/
public function user_categoryOverlay(): string
{
$html = '';
$languages = $this->getAllLanguages();
// if any language is available
if (count($languages) > 0) {
$html = '<select name="data[newsoverlay]" id="field_newsoverlay" class="form-control">';
if (!isset($languages[0])) {
$html .= '<option value="0">' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.default_value')) . '</option>';
}
foreach ($languages as $language) {
$selected = ((int)($GLOBALS['BE_USER']->uc['newsoverlay'] ?? 0) === (int)$language['uid']) ? ' selected="selected" ' : '';
$html .= '<option ' . $selected . 'value="' . $language['uid'] . '">' . htmlspecialchars($language['title']) . '</option>';
}
$html .= '</select>';
} else {
$html .= htmlspecialchars(
$this->getLanguageService()->sL(
'LLL:EXT:news/Resources/Private/Language/locallang_be.xlf:usersettings.no-languages-available'
)
);
}
return $html;
}
/**
* Get all languages
*
* @return array
*/
protected function getAllLanguages(): array
{
$versionInformation = GeneralUtility::makeInstance(Typo3Version::class);
if ($versionInformation->getMajorVersion() === 10) {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('sys_language');
return $queryBuilder->select('*')
->from('sys_language')
->orderBy('sorting')
->execute()
->fetchAll();
}
$siteLanguages = [];
foreach (GeneralUtility::makeInstance(SiteFinder::class)->getAllSites() as $site) {
foreach ($site->getAllLanguages() as $languageId => $language) {
if (!isset($siteLanguages[$languageId])) {
$siteLanguages[$languageId] = [
'uid' => $languageId,
'title' => $language->getTitle(),
];
}
}
}
return $siteLanguages;
}
/**
* Get tt_content record
*
* @param int $uid
*
* @return array|null
*/
protected function getContentElementRow($uid): ?array
{
return BackendUtilityCore::getRecord('tt_content', $uid);
}
/**
* Get page id, if negative, then it is a "after record"
*
* @param int $pid
* @return int
*/
protected function getPageId($pid): int
{
$pid = (int)$pid;
if ($pid > 0) {
return $pid;
}
$row = BackendUtilityCore::getRecord('tt_content', abs($pid), 'uid,pid');
return $row['pid'];
}
/**
* Returns LanguageService
*
* @return \TYPO3\CMS\Core\Localization\LanguageService
*/
protected function getLanguageService(): \TYPO3\CMS\Core\Localization\LanguageService
{
return $GLOBALS['LANG'];
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace GeorgRinger\News\Hooks;
/**
* 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 GeorgRinger\News\Service\CategoryService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Userfunc to get alternative label
*/
class Labels
{
/**
* Generate additional label for category records
* including the title of the parent category
*
* @param array $params
*
* @return void
*/
public function getUserLabelCategory(array &$params): void
{
$showTranslationInformation = false;
$getVars = GeneralUtility::_GET();
if (isset($getVars['route']) && $getVars['route'] === '/record/edit'
&& isset($getVars['edit']) && is_array($getVars['edit'])
&& (isset($getVars['edit']['tt_content']) || isset($getVars['edit']['tx_news_domain_model_news']) || isset($getVars['edit']['sys_category']))
) {
$showTranslationInformation = true;
}
if ($showTranslationInformation && is_array($params['row'])) {
$params['title'] = CategoryService::translateCategoryRecord($params['row']['title'], $params['row']);
} else {
$params['title'] = $params['row']['title'];
}
}
}

View File

@@ -0,0 +1,770 @@
<?php
namespace GeorgRinger\News\Hooks;
/**
* 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 GeorgRinger\News\Utility\TemplateLayout;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Template\DocumentTemplate;
use TYPO3\CMS\Backend\Utility\BackendUtility as BackendUtilityCore;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
/**
* Hook to display verbose information about pi1 plugin in Web>Page module
*/
class PageLayoutView
{
/**
* Extension key
*
* @var string
*/
const KEY = 'news';
/**
* Path to the locallang file
*
* @var string
*/
const LLPATH = 'LLL:EXT:news/Resources/Private/Language/locallang_be.xlf:';
/**
* Max shown settings
*/
const SETTINGS_IN_PREVIEW = 7;
/**
* Table information
*
* @var array
*/
public $tableData = [];
/**
* Flexform information
*
* @var array
*/
public $flexformData = [];
/**
* @var IconFactory
*/
protected $iconFactory;
/** @var TemplateLayout $templateLayoutsUtility */
protected $templateLayoutsUtility;
/**
* PageLayoutView constructor.
* @param TemplateLayout $templateLayout
* @param IconFactory $iconFactory
*/
public function __construct(
TemplateLayout $templateLayout,
IconFactory $iconFactory
) {
$this->templateLayoutsUtility = $templateLayout;
$this->iconFactory = $iconFactory;
}
/**
* Returns information about this extension's pi1 plugin
*
* @param array $params Parameters to the hook
* @return string Information about pi1 plugin
*/
public function getExtensionSummary(array $params): string
{
$actionTranslationKey = $result = '';
$header = '<strong>' . htmlspecialchars($this->getLanguageService()->sL(self::LLPATH . 'pi1_title')) . '</strong>';
if ($params['row']['list_type'] == self::KEY . '_pi1') {
$this->tableData = [];
$this->flexformData = GeneralUtility::xml2array($params['row']['pi_flexform']);
// if flexform data is found
$actions = $this->getFieldFromFlexform('switchableControllerActions');
if (!empty($actions)) {
$actionList = GeneralUtility::trimExplode(';', $actions);
// translate the first action into its translation
$actionTranslationKey = strtolower(str_replace('->', '_', $actionList[0]));
$actionTranslation = $this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.mode.' . $actionTranslationKey);
$header .= '<br><strong style="text-transform: uppercase">' . htmlspecialchars($actionTranslation) . '</strong>';
} else {
$header .= $this->generateCallout($this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.mode.not_configured'));
}
if (is_array($this->flexformData)) {
switch ($actionTranslationKey) {
case 'news_list':
$this->getStartingPoint();
$this->getCategorySettings();
$this->getDetailPidSetting();
$this->getTimeRestrictionSetting();
$this->getTemplateLayoutSettings($params['row']['pid']);
$this->getArchiveSettings();
$this->getTopNewsRestrictionSetting();
$this->getOrderSettings();
$this->getOffsetLimitSettings();
$this->getListPidSetting();
$this->getTagRestrictionSetting();
break;
case 'news_selectedlist':
$this->getSelectedListSetting();
$this->getOrderSettings();
break;
case 'news_detail':
$this->getSingleNewsSettings();
$this->getDetailPidSetting();
$this->getTemplateLayoutSettings($params['row']['pid']);
break;
case 'news_datemenu':
$this->getStartingPoint();
$this->getTimeRestrictionSetting();
$this->getTopNewsRestrictionSetting();
$this->getArchiveSettings();
$this->getDateMenuSettings();
$this->getCategorySettings();
$this->getTemplateLayoutSettings($params['row']['pid']);
break;
case 'category_list':
$this->getCategorySettings(false);
$this->getTemplateLayoutSettings($params['row']['pid']);
break;
case 'tag_list':
$this->getStartingPoint();
$this->getListPidSetting();
$this->getOrderSettings();
$this->getTemplateLayoutSettings($params['row']['pid']);
break;
default:
$this->getTemplateLayoutSettings($params['row']['pid']);
}
if ($hooks = $GLOBALS['TYPO3_CONF_VARS']['EXT']['news']['GeorgRinger\\News\\Hooks\\PageLayoutView']['extensionSummary'] ?? []) {
$params = [
'action' => $actionTranslationKey
];
foreach ($hooks as $reference) {
GeneralUtility::callUserFunction($reference, $params, $this);
}
}
// for all views
$this->getOverrideDemandSettings();
$result = $this->renderSettingsAsTable($header, $params['row']['uid'] ?? 0);
}
}
return $result;
}
/**
* Render archive settings
*
* @return void
*/
public function getArchiveSettings(): void
{
$archive = $this->getFieldFromFlexform('settings.archiveRestriction');
if (!empty($archive)) {
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.archiveRestriction'),
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.archiveRestriction.' . $archive)
];
}
}
/**
* Render single news settings
*
* @return void
*/
public function getSingleNewsSettings(): void
{
$singleNewsRecord = (int)$this->getFieldFromFlexform('settings.singleNews');
if ($singleNewsRecord > 0) {
$newsRecord = BackendUtilityCore::getRecord('tx_news_domain_model_news', $singleNewsRecord);
if (is_array($newsRecord)) {
$pageRecord = BackendUtilityCore::getRecord('pages', $newsRecord['pid']);
if (is_array($pageRecord)) {
$content = $this->getRecordData($newsRecord['uid'], 'tx_news_domain_model_news');
} else {
$text = sprintf(
$this->getLanguageService()->sL(self::LLPATH . 'pagemodule.pageNotAvailable'),
$newsRecord['pid']
);
$content = $this->generateCallout($text);
}
} else {
$text = sprintf(
$this->getLanguageService()->sL(self::LLPATH . 'pagemodule.newsNotAvailable'),
$singleNewsRecord
);
$content = $this->generateCallout($text);
}
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.singleNews'),
$content
];
}
}
/**
* Render single news settings
*
* @return void
*/
public function getDetailPidSetting(): void
{
$detailPid = (int)$this->getFieldFromFlexform('settings.detailPid', 'additional');
if ($detailPid > 0) {
$content = $this->getRecordData($detailPid);
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_additional.detailPid'),
$content
];
}
}
/**
* Render listPid news settings
*
* @return void
*/
public function getListPidSetting(): void
{
$listPid = (int)$this->getFieldFromFlexform('settings.listPid', 'additional');
if ($listPid > 0) {
$content = $this->getRecordData($listPid);
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_additional.listPid'),
$content
];
}
}
/**
* Get the rendered page title including onclick menu
*
* @param int $detailPid
* @return string
* @deprecated use getRecordData() instead
*/
public function getPageRecordData($detailPid): string
{
return $this->getRecordData($detailPid, 'pages');
}
/**
* @param int $id
* @param string $table
* @return string
*/
public function getRecordData($id, $table = 'pages'): string
{
$record = BackendUtilityCore::getRecord($table, $id);
if (is_array($record)) {
$data = '<span data-toggle="tooltip" data-placement="top" data-title="id=' . $record['uid'] . '">'
. $this->iconFactory->getIconForRecord($table, $record, Icon::SIZE_SMALL)->render()
. '</span> ';
$content = BackendUtilityCore::wrapClickMenuOnIcon(
$data,
$table,
$record['uid'],
true,
'',
'+info,edit,history'
);
$linkTitle = htmlspecialchars(BackendUtilityCore::getRecordTitle($table, $record));
if ($table === 'pages') {
$id = $record['uid'];
$currentPageId = (int)GeneralUtility::_GET('id');
$link = htmlspecialchars($this->getEditLink($record, $currentPageId));
$switchLabel = $this->getLanguageService()->sL(self::LLPATH . 'pagemodule.switchToPage');
$content .= ' <a href="#" data-toggle="tooltip" data-placement="top" data-title="' . $switchLabel . '" onclick=\'top.jump("' . $link . '", "web_layout", "web", ' . $id . ');return false\'>' . $linkTitle . '</a>';
} else {
$content .= $linkTitle;
}
} else {
$text = sprintf(
$this->getLanguageService()->sL(self::LLPATH . 'pagemodule.recordNotAvailable'),
$id
);
$content = $this->generateCallout($text);
}
return $content;
}
/**
* Get order settings
*
* @return void
*/
public function getOrderSettings(): void
{
$orderField = $this->getFieldFromFlexform('settings.orderBy');
if (!empty($orderField)) {
$text = $this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.orderBy.' . $orderField);
// Order direction (asc, desc)
$orderDirection = $this->getOrderDirectionSetting();
if ($orderDirection) {
$text .= ', ' . strtolower($orderDirection);
}
// Top news first
$topNews = $this->getTopNewsFirstSetting();
if ($topNews) {
$text .= '<br />' . $topNews;
}
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.orderBy'),
$text
];
}
}
/**
* Get order direction
*
* @return string
*/
public function getOrderDirectionSetting(): string
{
$text = '';
$orderDirection = $this->getFieldFromFlexform('settings.orderDirection');
if (!empty($orderDirection)) {
$text = $this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.orderDirection.' . $orderDirection);
}
return $text;
}
/**
* Get topNewsFirst setting
*
* @return string
*/
public function getTopNewsFirstSetting(): string
{
$text = '';
$topNewsSetting = (int)$this->getFieldFromFlexform('settings.topNewsFirst', 'additional');
if ($topNewsSetting === 1) {
$text = $this->getLanguageService()->sL(self::LLPATH . 'flexforms_additional.topNewsFirst');
}
return $text;
}
/**
* Render category settings
*
* @param bool $showCategoryMode show the category conjunction
*
* @return void
*/
public function getCategorySettings($showCategoryMode = true): void
{
$categories = GeneralUtility::intExplode(',', $this->getFieldFromFlexform('settings.categories') ?? '', true);
if (count($categories) > 0) {
$categoriesOut = [];
foreach ($categories as $id) {
$categoriesOut[] = $this->getRecordData($id, 'sys_category');
}
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.categories'),
implode(', ', $categoriesOut)
];
// Category mode
if ($showCategoryMode) {
$categoryModeSelection = $this->getFieldFromFlexform('settings.categoryConjunction');
if (empty($categoryModeSelection)) {
$categoryMode = $this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.categoryConjunction.all');
} else {
$categoryMode = $this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.categoryConjunction.' . $categoryModeSelection);
}
if (count($categories) > 0 && empty($categoryModeSelection)) {
$categoryMode = $this->generateCallout($categoryMode);
} else {
$categoryMode = htmlspecialchars($categoryMode);
}
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.categoryConjunction'),
$categoryMode
];
}
$includeSubcategories = $this->getFieldFromFlexform('settings.includeSubCategories');
if ($includeSubcategories) {
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.includeSubCategories'),
'<i class="fa fa-check"></i>'
];
}
}
}
/**
* Get the restriction for tags
*
* @return void
*/
public function getTagRestrictionSetting()
{
$tags = GeneralUtility::intExplode(',', $this->getFieldFromFlexform('settings.tags', 'additional') ?? '', true);
if (count($tags) === 0) {
return;
}
$categoryTitles = [];
foreach ($tags as $id) {
$categoryTitles[] = $this->getRecordData($id, 'tx_news_domain_model_tag');
}
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_additional.tags'),
implode(', ', $categoryTitles)
];
}
/**
* Render offset & limit configuration
*
* @return void
*/
public function getOffsetLimitSettings(): void
{
$offset = $this->getFieldFromFlexform('settings.offset', 'additional');
$limit = $this->getFieldFromFlexform('settings.limit', 'additional');
$hidePagination = $this->getFieldFromFlexform('settings.hidePagination', 'additional');
if ($offset) {
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_additional.offset'),
$offset
];
}
if ($limit) {
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_additional.limit'),
$limit
];
}
if ($hidePagination) {
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_additional.hidePagination'),
'<i class="fa fa-check"></i>'
];
}
}
/**
* Render date menu configuration
*
* @return void
*/
public function getDateMenuSettings(): void
{
$dateMenuField = $this->getFieldFromFlexform('settings.dateField');
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.dateField'),
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.dateField.' . $dateMenuField)
];
}
/**
* Render time restriction configuration
*
* @return void
*/
public function getTimeRestrictionSetting(): void
{
$timeRestriction = $this->getFieldFromFlexform('settings.timeRestriction');
if (!empty($timeRestriction)) {
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.timeRestriction'),
htmlspecialchars($timeRestriction)
];
}
$timeRestrictionHigh = $this->getFieldFromFlexform('settings.timeRestrictionHigh');
if (!empty($timeRestrictionHigh)) {
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.timeRestrictionHigh'),
htmlspecialchars($timeRestrictionHigh)
];
}
}
/**
* Render top news restriction configuration
*
* @return void
*/
public function getTopNewsRestrictionSetting(): void
{
$topNewsRestriction = (int)$this->getFieldFromFlexform('settings.topNewsRestriction');
if ($topNewsRestriction > 0) {
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.topNewsRestriction'),
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.topNewsRestriction.' . $topNewsRestriction)
];
}
}
/**
* Render template layout configuration
*
* @param int $pageUid
*
* @return void
*/
public function getTemplateLayoutSettings($pageUid): void
{
$title = '';
$field = $this->getFieldFromFlexform('settings.templateLayout', 'template');
// Find correct title by looping over all options
if (!empty($field)) {
$layouts = $this->templateLayoutsUtility->getAvailableTemplateLayouts($pageUid);
foreach ($layouts as $layout) {
if ((string)$layout[1] === (string)$field) {
$title = $layout[0];
}
}
}
if (!empty($title)) {
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_template.templateLayout'),
$this->getLanguageService()->sL($title)
];
}
}
/**
* Get information if override demand setting is disabled or not
*
* @return void
*/
public function getOverrideDemandSettings(): void
{
$field = $this->getFieldFromFlexform('settings.disableOverrideDemand', 'additional');
if ($field == 1) {
$this->tableData[] = [
$this->getLanguageService()->sL(
self::LLPATH . 'flexforms_additional.disableOverrideDemand'
),
'<i class="fa fa-check"></i>'
];
}
}
/**
* Get the startingpoint
*
* @return void
*/
public function getStartingPoint(): void
{
$value = $this->getFieldFromFlexform('settings.startingpoint');
if (!empty($value)) {
$pageIds = GeneralUtility::intExplode(',', $value, true);
$pagesOut = [];
foreach ($pageIds as $id) {
$pagesOut[] = $this->getRecordData($id, 'pages');
}
$recursiveLevel = (int)$this->getFieldFromFlexform('settings.recursive');
$recursiveLevelText = '';
if ($recursiveLevel === 250) {
$recursiveLevelText = $this->getLanguageService()->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:recursive.I.5');
} elseif ($recursiveLevel > 0) {
$recursiveLevelText = $this->getLanguageService()->sL('LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:recursive.I.' . $recursiveLevel);
}
if (!empty($recursiveLevelText)) {
$recursiveLevelText = '<br />' .
htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.recursive')) . ' ' .
$recursiveLevelText;
}
$this->tableData[] = [
$this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.startingpoint'),
implode(', ', $pagesOut) . $recursiveLevelText
];
}
}
/**
* Get list of selected news items
*
* @return void
*/
protected function getSelectedListSetting(): void
{
$value = $this->getFieldFromFlexform('settings.selectedList');
if (!empty($value)) {
$idList = GeneralUtility::intExplode(',', $value, true);
$out = [];
foreach ($idList as $id) {
$out[] = $this->getRecordData($id, 'tx_news_domain_model_news');
}
$this->tableData[] = [
$this->getLanguageService()->sL(self::LLPATH . 'flexforms_general.selectedList'),
implode('<br>', $out)
];
}
}
/**
* Render an alert box
*
* @param string $text
* @return string
*/
protected function generateCallout($text): string
{
return '<div class="alert alert-warning">
' . htmlspecialchars($text) . '
</div>';
}
/**
* Render the settings as table for Web>Page module
* System settings are displayed in mono font
*
* @param string $header
* @param int $recordUid
* @return string
*/
protected function renderSettingsAsTable($header = '', $recordUid = 0): string
{
$pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
$pageRenderer->loadRequireJsModule('TYPO3/CMS/News/PageLayout');
$pageRenderer->addCssFile('EXT:news/Resources/Public/Css/Backend/PageLayoutView.css');
$view = GeneralUtility::makeInstance(StandaloneView::class);
$view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName('EXT:news/Resources/Private/Backend/PageLayoutView.html'));
$view->assignMultiple([
'header' => $header,
'rows' => [
'above' => array_slice($this->tableData, 0, self::SETTINGS_IN_PREVIEW),
'below' => array_slice($this->tableData, self::SETTINGS_IN_PREVIEW)
],
'id' => $recordUid
]);
return $view->render();
}
/**
* Get field value from flexform configuration,
* including checks if flexform configuration is available
*
* @param string $key name of the key
* @param string $sheet name of the sheet
* @return string|null if nothing found, value if found
*/
public function getFieldFromFlexform($key, $sheet = 'sDEF'): ?string
{
$flexform = $this->flexformData;
if (isset($flexform['data'])) {
$flexform = $flexform['data'];
if (isset($flexform[$sheet]['lDEF'][$key]['vDEF'])
) {
return $flexform[$sheet]['lDEF'][$key]['vDEF'];
}
}
return null;
}
/**
* Build a backend edit link based on given record.
*
* @param array $row Current record row from database.
* @param int $currentPageUid current page uid
* @return string Link to open an edit window for record.
* @see \TYPO3\CMS\Backend\Utility\BackendUtilityCore::readPageAccess()
*/
protected function getEditLink($row, $currentPageUid): string
{
$editLink = '';
$localCalcPerms = $GLOBALS['BE_USER']->calcPerms(BackendUtilityCore::getRecord('pages', $row['uid']));
$permsEdit = $localCalcPerms & Permission::PAGE_EDIT;
if ($permsEdit) {
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
$returnUrl = $uriBuilder->buildUriFromRoute('web_layout', ['id' => $currentPageUid]);
$editLink = $uriBuilder->buildUriFromRoute('web_layout', [
'id' => $row['uid'],
'returnUrl' => $returnUrl
]);
}
return $editLink;
}
/**
* Return language service instance
*
* @return \TYPO3\CMS\Core\Localization\LanguageService
*/
public function getLanguageService(): \TYPO3\CMS\Core\Localization\LanguageService
{
return $GLOBALS['LANG'];
}
/**
* Get the DocumentTemplate
*
* @return DocumentTemplate
*/
protected function getDocumentTemplate(): DocumentTemplate
{
return $GLOBALS['TBE_TEMPLATE'];
}
}