first commit
This commit is contained in:
commit
1218dd1517
12716 files changed
+989233
No files matched your search
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
namespace TYPO3\CMS\Backend\Configuration;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Convenience wrapper for backend user configuration
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class BackendUserConfiguration
|
||||
{
|
||||
/**
|
||||
* @var BackendUserAuthentication
|
||||
*/
|
||||
protected $backendUser;
|
||||
|
||||
/**
|
||||
* @param BackendUserAuthentication|null $backendUser
|
||||
*/
|
||||
public function __construct(BackendUserAuthentication $backendUser = null)
|
||||
{
|
||||
$this->backendUser = $backendUser ?: $GLOBALS['BE_USER'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specific user setting
|
||||
*
|
||||
* @param string $key Identifier, allows also dotted notation for subarrays
|
||||
* @return mixed Value associated
|
||||
*/
|
||||
public function get(string $key)
|
||||
{
|
||||
return (strpos($key, '.') !== false) ? $this->getFromDottedNotation($key) : $this->backendUser->uc[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all user settings
|
||||
*
|
||||
* @return mixed all values, usually a multi-dimensional array
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
return $this->backendUser->uc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets user settings by key/value pair
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function set(string $key, $value): void
|
||||
{
|
||||
if (strpos($key, '.') !== false) {
|
||||
$this->setFromDottedNotation($key, $value);
|
||||
} else {
|
||||
$this->backendUser->uc[$key] = $value;
|
||||
}
|
||||
|
||||
$this->backendUser->writeUC($this->backendUser->uc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an value to an Comma-separated list
|
||||
* stored in $key of user settings
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function addToList(string $key, $value): void
|
||||
{
|
||||
$list = $this->get($key);
|
||||
|
||||
if (!isset($list)) {
|
||||
$list = $value;
|
||||
} elseif (!GeneralUtility::inList($list, $value)) {
|
||||
$list .= ',' . $value;
|
||||
}
|
||||
|
||||
$this->set($key, $list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an value from an Comma-separated list
|
||||
* stored $key of user settings
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function removeFromList(string $key, $value): void
|
||||
{
|
||||
$list = $this->get($key);
|
||||
|
||||
if (GeneralUtility::inList($list, $value)) {
|
||||
$list = GeneralUtility::trimExplode(',', $list, true);
|
||||
$list = ArrayUtility::removeArrayEntryByValue($list, $value);
|
||||
$this->set($key, implode(',', $list));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the user settings to the default
|
||||
*/
|
||||
public function clear(): void
|
||||
{
|
||||
$this->backendUser->resetUC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a key in user settings
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
public function unsetOption(string $key): void
|
||||
{
|
||||
if (isset($this->backendUser->uc[$key])) {
|
||||
unset($this->backendUser->uc[$key]);
|
||||
$this->backendUser->writeUC($this->backendUser->uc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the subarray from dotted notation
|
||||
*
|
||||
* @param string $key Dotted notation of subkeys like moduleData.module1.general.checked
|
||||
* @return mixed value of the settings
|
||||
*/
|
||||
protected function getFromDottedNotation(string $key)
|
||||
{
|
||||
$subkeys = GeneralUtility::trimExplode('.', $key);
|
||||
$configuration = $this->backendUser->uc;
|
||||
|
||||
foreach ($subkeys as $subkey) {
|
||||
if (isset($configuration[$subkey])) {
|
||||
$configuration = &$configuration[$subkey];
|
||||
} else {
|
||||
$configuration = [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a key written in dotted notation
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
protected function setFromDottedNotation(string $key, $value): void
|
||||
{
|
||||
$subkeys = GeneralUtility::trimExplode('.', $key, true);
|
||||
$lastKey = $subkeys[count($subkeys) - 1];
|
||||
$configuration = &$this->backendUser->uc;
|
||||
|
||||
foreach ($subkeys as $subkey) {
|
||||
if ($subkey === $lastKey) {
|
||||
$configuration[$subkey] = $value;
|
||||
} else {
|
||||
$configuration = &$configuration[$subkey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace TYPO3\CMS\Backend\Configuration;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use TYPO3\CMS\Core\Package\PackageManager;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Helper class for the backend "Sites" module
|
||||
*
|
||||
* Load Site configuration TCA from ext:*Configuration/SiteConfiguration
|
||||
* and ext:*Configuration/SiteConfiguration/Overrides
|
||||
*
|
||||
* @internal This class is a specific Backend implementation and is not considered part of the Public TYPO3 API.
|
||||
*/
|
||||
class SiteTcaConfiguration
|
||||
{
|
||||
/**
|
||||
* Returns a "fake TCA" array that is syntactically identical to
|
||||
* "normal" TCA, but is not available as $GLOBALS['TCA']. During
|
||||
* configuration loading time, the target array is available as
|
||||
* $GLOBALS['SiteConfiguration'] within the Overrides files.
|
||||
*
|
||||
* It is not possible to use ExtensionManagementUtility methods.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTca(): array
|
||||
{
|
||||
$GLOBALS['SiteConfiguration'] = [];
|
||||
$activePackages = GeneralUtility::makeInstance(PackageManager::class)->getActivePackages();
|
||||
// First load "full table" files from Configuration/SiteConfiguration
|
||||
$finder = (new Finder())->files()->depth(0)->name('*.php');
|
||||
$hasDirectoryEntries = false;
|
||||
foreach ($activePackages as $package) {
|
||||
try {
|
||||
$finder->in($package->getPackagePath() . 'Configuration/SiteConfiguration');
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
// No such directory in this package
|
||||
continue;
|
||||
}
|
||||
$hasDirectoryEntries = true;
|
||||
}
|
||||
if ($hasDirectoryEntries) {
|
||||
foreach ($finder as $fileInfo) {
|
||||
$GLOBALS['SiteConfiguration'][substr($fileInfo->getBasename(), 0, -4)] = require $fileInfo->getPathname();
|
||||
}
|
||||
}
|
||||
// Execute override files from Configuration/SiteConfiguration/Overrides
|
||||
$finder = (new Finder())->files()->depth(0)->name('*.php');
|
||||
$hasDirectoryEntries = false;
|
||||
foreach ($activePackages as $package) {
|
||||
try {
|
||||
$finder->in($package->getPackagePath() . 'Configuration/SiteConfiguration/Overrides');
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
// No such directory in this package
|
||||
continue;
|
||||
}
|
||||
$hasDirectoryEntries = true;
|
||||
}
|
||||
if ($hasDirectoryEntries) {
|
||||
foreach ($finder as $fileInfo) {
|
||||
require $fileInfo->getPathname();
|
||||
}
|
||||
}
|
||||
$result = $GLOBALS['SiteConfiguration'];
|
||||
unset($GLOBALS['SiteConfiguration']);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
namespace TYPO3\CMS\Backend\Configuration\TCA;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
|
||||
/**
|
||||
* This class provides user functions for the usage in TCA definition
|
||||
* @internal
|
||||
*/
|
||||
class UserFunctions
|
||||
{
|
||||
/**
|
||||
* Used to build the IRRE title of a site language element
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function getSiteLanguageTitle(array &$parameters): void
|
||||
{
|
||||
$record = $parameters['row'];
|
||||
$parameters['title'] = sprintf(
|
||||
'%s %s (%s) Base: %s',
|
||||
$record['enabled'] ? '' : '[' . $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:disabled') . ']',
|
||||
$record['title'],
|
||||
$record['locale'],
|
||||
$record['base']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to build the IRRE title of a site route element
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function getRouteTitle(array &$parameters): void
|
||||
{
|
||||
$record = $parameters['row'];
|
||||
if ($record['type'][0] === 'uri') {
|
||||
$parameters['title'] = sprintf(
|
||||
'%s %s %s',
|
||||
$record['route'],
|
||||
$this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_siteconfiguration_tca.xlf:site.routes.irreHeader.redirectsTo'),
|
||||
$record['source'] ?: '[' . $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_common.xlf:undefined') . ']'
|
||||
);
|
||||
} else {
|
||||
$parameters['title'] = $record['route'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to build the IRRE title of a site error handling element
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function getErrorHandlingTitle(array &$parameters): void
|
||||
{
|
||||
$record = $parameters['row'];
|
||||
$format = '%s: %s';
|
||||
$arguments = [$record['errorCode']];
|
||||
switch ($record['errorHandler'][0]) {
|
||||
case 'Fluid':
|
||||
$arguments[] = $record['errorFluidTemplate'];
|
||||
break;
|
||||
case 'Page':
|
||||
$arguments[] = $record['errorContentSource'];
|
||||
break;
|
||||
case 'PHP':
|
||||
$arguments[] = $record['errorPhpClassFQCN'];
|
||||
break;
|
||||
default:
|
||||
$arguments[] = $record['errorHandler'][0];
|
||||
}
|
||||
$parameters['title'] = sprintf($format, ...$arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LanguageService
|
||||
*/
|
||||
protected function getLanguageService(): LanguageService
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
namespace TYPO3\CMS\Backend\Configuration;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
|
||||
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Routing\SiteMatcher;
|
||||
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Contains translation tools
|
||||
*
|
||||
* @internal The whole class is subject to be removed, fetch all language info from the current site object.
|
||||
*/
|
||||
class TranslationConfigurationProvider
|
||||
{
|
||||
/**
|
||||
* @return LanguageService
|
||||
*/
|
||||
protected function getLanguageService()
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of system languages
|
||||
* The property flagIcon returns a string <flags-xx>.
|
||||
*
|
||||
* @param int $pageId Page id (used to get TSconfig configuration setting flag and label for default language)
|
||||
* @return array Array with languages (uid, title, ISOcode, flagIcon)
|
||||
*/
|
||||
public function getSystemLanguages($pageId = 0)
|
||||
{
|
||||
try {
|
||||
$site = GeneralUtility::makeInstance(SiteMatcher::class)->matchByPageId((int)$pageId);
|
||||
$siteLanguages = $site->getAvailableLanguages($this->getBackendUserAuthentication(), true);
|
||||
|
||||
if (!isset($siteLanguages[0])) {
|
||||
$siteLanguages[0] = $site->getDefaultLanguage();
|
||||
ksort($siteLanguages);
|
||||
}
|
||||
|
||||
$languages = [];
|
||||
foreach ($siteLanguages as $id => $siteLanguage) {
|
||||
$languages[$id] = [
|
||||
'uid' => $id,
|
||||
'title' => $siteLanguage->getTitle(),
|
||||
'ISOcode' => $siteLanguage->getTwoLetterIsoCode(),
|
||||
'flagIcon' => $siteLanguage->getFlagIdentifier(),
|
||||
];
|
||||
}
|
||||
} catch (SiteNotFoundException $e) {
|
||||
// default language and "all languages" are always present
|
||||
$modSharedTSconfig = BackendUtility::getPagesTSconfig($pageId)['mod.']['SHARED.'] ?? [];
|
||||
$languages = [
|
||||
// 0: default language
|
||||
0 => [
|
||||
'uid' => 0,
|
||||
'title' => $this->getDefaultLanguageLabel($modSharedTSconfig),
|
||||
'ISOcode' => 'DEF',
|
||||
'flagIcon' => $this->getDefaultLanguageFlag($modSharedTSconfig),
|
||||
],
|
||||
// -1: all languages
|
||||
-1 => [
|
||||
'uid' => -1,
|
||||
'title' => $this->getLanguageService()->getLL('multipleLanguages'),
|
||||
'ISOcode' => 'DEF',
|
||||
'flagIcon' => 'flags-multiple',
|
||||
],
|
||||
];
|
||||
|
||||
// add the additional languages from database records
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_language');
|
||||
$languageRecords = $queryBuilder
|
||||
->select('*')
|
||||
->from('sys_language')
|
||||
->orderBy('sorting')
|
||||
->execute()
|
||||
->fetchAll();
|
||||
foreach ($languageRecords as $languageRecord) {
|
||||
$languages[$languageRecord['uid']] = $languageRecord;
|
||||
// @todo: this should probably resolve language_isocode too and throw a deprecation if not filled
|
||||
if ($languageRecord['static_lang_isocode'] && ExtensionManagementUtility::isLoaded('static_info_tables')) {
|
||||
$staticLangRow = BackendUtility::getRecord('static_languages', $languageRecord['static_lang_isocode'], 'lg_iso_2');
|
||||
if ($staticLangRow['lg_iso_2']) {
|
||||
$languages[$languageRecord['uid']]['ISOcode'] = $staticLangRow['lg_iso_2'];
|
||||
}
|
||||
}
|
||||
if ($languageRecord['flag'] !== '') {
|
||||
$languages[$languageRecord['uid']]['flagIcon'] = 'flags-' . $languageRecord['flag'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about translation for an element
|
||||
* Will overlay workspace version of record too!
|
||||
*
|
||||
* @param string $table Table name
|
||||
* @param int $uid Record uid
|
||||
* @param int $languageUid Language uid. If 0, then all languages are selected.
|
||||
* @param array $row The record to be translated
|
||||
* @param string $selFieldList Select fields for the query which fetches the translations of the current record
|
||||
* @return mixed Array with information or error message as a string.
|
||||
*/
|
||||
public function translationInfo($table, $uid, $languageUid = 0, array $row = null, $selFieldList = '')
|
||||
{
|
||||
if (!$GLOBALS['TCA'][$table] || !$uid) {
|
||||
return 'No table "' . $table . '" or no UID value';
|
||||
}
|
||||
if ($row === null) {
|
||||
$row = BackendUtility::getRecordWSOL($table, $uid);
|
||||
}
|
||||
if (!is_array($row)) {
|
||||
return 'Record "' . $table . '_' . $uid . '" was not found';
|
||||
}
|
||||
if (!BackendUtility::isTableLocalizable($table)) {
|
||||
return 'Translation is not supported for this table!';
|
||||
}
|
||||
if ($row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] > 0) {
|
||||
return 'Record "' . $table . '_' . $uid . '" seems to be a translation already (has a language value "' . $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']] . '", relation to record "' . $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] . '")';
|
||||
}
|
||||
if ($row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] != 0) {
|
||||
return 'Record "' . $table . '_' . $uid . '" seems to be a translation already (has a relation to record "' . $row[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] . '")';
|
||||
}
|
||||
// Look for translations of this record, index by language field value:
|
||||
if (!$selFieldList) {
|
||||
$selFieldList = 'uid,' . $GLOBALS['TCA'][$table]['ctrl']['languageField'];
|
||||
}
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
|
||||
$queryBuilder->getRestrictions()
|
||||
->removeAll()
|
||||
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
|
||||
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
|
||||
$queryBuilder
|
||||
->select(...GeneralUtility::trimExplode(',', $selFieldList))
|
||||
->from($table)
|
||||
->where(
|
||||
$queryBuilder->expr()->eq(
|
||||
$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'],
|
||||
$queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
|
||||
),
|
||||
$queryBuilder->expr()->eq(
|
||||
'pid',
|
||||
$queryBuilder->createNamedParameter(
|
||||
$row['pid'],
|
||||
\PDO::PARAM_INT
|
||||
)
|
||||
)
|
||||
);
|
||||
if (!$languageUid) {
|
||||
$queryBuilder->andWhere(
|
||||
$queryBuilder->expr()->gt(
|
||||
$GLOBALS['TCA'][$table]['ctrl']['languageField'],
|
||||
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$queryBuilder
|
||||
->andWhere(
|
||||
$queryBuilder->expr()->eq(
|
||||
$GLOBALS['TCA'][$table]['ctrl']['languageField'],
|
||||
$queryBuilder->createNamedParameter($languageUid, \PDO::PARAM_INT)
|
||||
)
|
||||
);
|
||||
}
|
||||
$translationRecords = $queryBuilder
|
||||
->execute()
|
||||
->fetchAll();
|
||||
|
||||
$translations = [];
|
||||
$translationsErrors = [];
|
||||
foreach ($translationRecords as $translationRecord) {
|
||||
if (!isset($translations[$translationRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']]])) {
|
||||
$translations[$translationRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']]] = $translationRecord;
|
||||
} else {
|
||||
$translationsErrors[$translationRecord[$GLOBALS['TCA'][$table]['ctrl']['languageField']]][] = $translationRecord;
|
||||
}
|
||||
}
|
||||
return [
|
||||
'table' => $table,
|
||||
'uid' => $uid,
|
||||
'CType' => $row['CType'],
|
||||
'sys_language_uid' => $row[$GLOBALS['TCA'][$table]['ctrl']['languageField']],
|
||||
'translations' => $translations,
|
||||
'excessive_translations' => $translationsErrors
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the table in which translations for input table is found.
|
||||
*
|
||||
* @param string $table The table name
|
||||
* @return string
|
||||
* @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0 as foreign translation table is not supported anymore
|
||||
*/
|
||||
public function getTranslationTable($table)
|
||||
{
|
||||
trigger_error('TranslationConfigurationProvider->getTranslationTable() will be removed in TYPO3 v10.0, as the translation table is always the same as the original table.', E_USER_DEPRECATED);
|
||||
return BackendUtility::isTableLocalizable($table) ? $table : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE, if the input table has localization enabled and done so with records from the same table
|
||||
*
|
||||
* @param string $table The table name
|
||||
* @return bool
|
||||
* @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0 as foreign translation table is not supported anymore
|
||||
*/
|
||||
public function isTranslationInOwnTable($table)
|
||||
{
|
||||
trigger_error('TranslationConfigurationProvider->isTranslationInOwnTable() will be removed in TYPO3 v10.0, as the translation table is always the same as the original table.', E_USER_DEPRECATED);
|
||||
return $GLOBALS['TCA'][$table]['ctrl']['languageField'] && $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns foreign translation table, if any.
|
||||
* Since TYPO3 v9, even "pages" translations are stored in the same table, having this method return always
|
||||
* empty, as with other tables as well.
|
||||
*
|
||||
* @param string $table The table name
|
||||
* @return string Translation foreign table
|
||||
* @deprecated since TYPO3 v9, will be removed in TYPO3 v10.0 as foreign translation table is not supported anymore
|
||||
*/
|
||||
public function foreignTranslationTable($table)
|
||||
{
|
||||
trigger_error('TranslationConfigurationProvider->foreignTranslationTable() will be removed in TYPO3 v10.0, as the translation table is always the same as the original table.', E_USER_DEPRECATED);
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $modSharedTSconfig
|
||||
* @return string
|
||||
*/
|
||||
protected function getDefaultLanguageFlag(array $modSharedTSconfig)
|
||||
{
|
||||
if (strlen($modSharedTSconfig['defaultLanguageFlag'])) {
|
||||
$defaultLanguageFlag = 'flags-' . $modSharedTSconfig['defaultLanguageFlag'];
|
||||
} else {
|
||||
$defaultLanguageFlag = 'empty-empty';
|
||||
}
|
||||
return $defaultLanguageFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $modSharedTSconfig
|
||||
* @return string
|
||||
*/
|
||||
protected function getDefaultLanguageLabel(array $modSharedTSconfig)
|
||||
{
|
||||
if (strlen($modSharedTSconfig['defaultLanguageLabel'])) {
|
||||
$defaultLanguageLabel = $modSharedTSconfig['defaultLanguageLabel'] . ' (' . $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage') . ')';
|
||||
} else {
|
||||
$defaultLanguageLabel = $this->getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:defaultLanguage');
|
||||
}
|
||||
return $defaultLanguageLabel;
|
||||
}
|
||||
|
||||
protected function getBackendUserAuthentication(): BackendUserAuthentication
|
||||
{
|
||||
return $GLOBALS['BE_USER'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\Configuration;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Core\Cache\CacheManager;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* A TS-Config parsing class which performs condition evaluation
|
||||
*/
|
||||
class TsConfigParser extends \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $rootLine = [];
|
||||
|
||||
/**
|
||||
* The uid of the page being handled
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $type;
|
||||
|
||||
/**
|
||||
* Parses the passed TS-Config using conditions and caching
|
||||
*
|
||||
* @param string $TStext The TSConfig being parsed
|
||||
* @param string $type The type of TSConfig (either "userTS" or "PAGES")
|
||||
* @param int $id The uid of the page being handled
|
||||
* @param array $rootLine The rootline of the page being handled
|
||||
* @return array Array containing the parsed TSConfig and a flag whether the content was retrieved from cache
|
||||
*/
|
||||
public function parseTSconfig($TStext, $type, $id = 0, array $rootLine = [])
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->id = $id;
|
||||
$this->rootLine = $rootLine;
|
||||
$hash = md5($type . ':' . $TStext);
|
||||
|
||||
$cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_hash');
|
||||
$cachedContent = $cache->get($hash);
|
||||
if (is_array($cachedContent)) {
|
||||
$storedData = $cachedContent[0];
|
||||
$storedMD5 = $cachedContent[1];
|
||||
$storedData['match'] = [];
|
||||
$storedData = $this->matching($storedData);
|
||||
$checkMD5 = md5(serialize($storedData));
|
||||
if ($checkMD5 == $storedMD5) {
|
||||
$res = [
|
||||
'TSconfig' => $storedData['TSconfig'],
|
||||
'cached' => 1,
|
||||
'hash' => $hash
|
||||
];
|
||||
} else {
|
||||
$shash = md5($checkMD5 . $hash);
|
||||
$cachedSpec = $cache->get($shash);
|
||||
if (is_array($cachedSpec)) {
|
||||
$storedData = $cachedSpec;
|
||||
$res = [
|
||||
'TSconfig' => $storedData['TSconfig'],
|
||||
'cached' => 1,
|
||||
'hash' => $shash
|
||||
];
|
||||
} else {
|
||||
$storeData = $this->parseWithConditions($TStext);
|
||||
$res = [
|
||||
'TSconfig' => $storeData['TSconfig'],
|
||||
'cached' => 0,
|
||||
'hash' => $shash
|
||||
];
|
||||
$cache->set($shash, $storeData, ['ident_' . $type . '_TSconfig'], 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$storeData = $this->parseWithConditions($TStext);
|
||||
$md5 = md5(serialize($storeData));
|
||||
$cache->set($hash, [$storeData, $md5], ['ident_' . $type . '_TSconfig'], 0);
|
||||
$res = [
|
||||
'TSconfig' => $storeData['TSconfig'],
|
||||
'cached' => 0,
|
||||
'hash' => $hash
|
||||
];
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the actual parsing using the parent objects "parse" method. Creates the match-Object
|
||||
*
|
||||
* @param string $TSconfig The TSConfig being parsed
|
||||
* @return array Array containing the parsed TSConfig, the encountered sectiosn, the matched sections
|
||||
*/
|
||||
protected function parseWithConditions($TSconfig)
|
||||
{
|
||||
/** @var \TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher $matchObj */
|
||||
$matchObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher::class);
|
||||
$matchObj->setRootline($this->rootLine);
|
||||
$matchObj->setPageId($this->id);
|
||||
$this->parse($TSconfig, $matchObj);
|
||||
return [
|
||||
'TSconfig' => $this->setup,
|
||||
'sections' => $this->sections,
|
||||
'match' => $this->sectionsMatch
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Is just going through an array of conditions to determine which are matching (for getting correct cache entry)
|
||||
*
|
||||
* @param array $cc An array containing the sections to match
|
||||
* @return array The input array with matching sections filled into the "match" key
|
||||
*/
|
||||
protected function matching(array $cc)
|
||||
{
|
||||
if (is_array($cc['sections'])) {
|
||||
/** @var \TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher $matchObj */
|
||||
$matchObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher::class);
|
||||
$matchObj->setRootline($this->rootLine);
|
||||
$matchObj->setPageId($this->id);
|
||||
foreach ($cc['sections'] as $key => $pre) {
|
||||
if ($matchObj->match($pre)) {
|
||||
$cc['match'][$key] = $pre;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $cc;
|
||||
}
|
||||
}
|
||||
+336
@@ -0,0 +1,336 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching;
|
||||
|
||||
/*
|
||||
* This file is part of the TYPO3 CMS project.
|
||||
*
|
||||
* It is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, either version 2
|
||||
* of the License, or any later version.
|
||||
*
|
||||
* For the full copyright and license information, please read the
|
||||
* LICENSE.txt file that was distributed with this source code.
|
||||
*
|
||||
* The TYPO3 project - inspiring people to share!
|
||||
*/
|
||||
|
||||
use TYPO3\CMS\Backend\Controller\EditDocumentController;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher;
|
||||
use TYPO3\CMS\Core\Context\Context;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Matching TypoScript conditions for backend disposal.
|
||||
*
|
||||
* Used with the TypoScript parser.
|
||||
* Matches browserinfo, IPnumbers for use with templates
|
||||
*/
|
||||
class ConditionMatcher extends AbstractConditionMatcher
|
||||
{
|
||||
/**
|
||||
* @var Context
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
public function __construct(Context $context = null)
|
||||
{
|
||||
$this->context = $context ?? GeneralUtility::makeInstance(Context::class);
|
||||
$this->rootline = $this->determineRootline() ?? [];
|
||||
$this->initializeExpressionLanguageResolver();
|
||||
}
|
||||
|
||||
protected function updateExpressionLanguageVariables(): void
|
||||
{
|
||||
$treeLevel = $this->rootline ? count($this->rootline) - 1 : 0;
|
||||
if ($this->isNewPageWithPageId($this->pageId)) {
|
||||
$treeLevel++;
|
||||
}
|
||||
$tree = new \stdClass();
|
||||
$tree->level = $treeLevel;
|
||||
$tree->rootLine = $this->rootline;
|
||||
$tree->rootLineIds = array_column($this->rootline, 'uid');
|
||||
|
||||
$backendUserAspect = $this->context->getAspect('backend.user');
|
||||
$backend = new \stdClass();
|
||||
$backend->user = new \stdClass();
|
||||
$backend->user->isAdmin = $backendUserAspect->get('isAdmin');
|
||||
$backend->user->isLoggedIn = $backendUserAspect->get('isLoggedIn');
|
||||
$backend->user->userId = $backendUserAspect->get('id');
|
||||
$backend->user->userGroupList = implode(',', $backendUserAspect->get('groupIds'));
|
||||
|
||||
$this->expressionLanguageResolverVariables = [
|
||||
'tree' => $tree,
|
||||
'backend' => $backend,
|
||||
'page' => BackendUtility::getRecord('pages', $this->pageId ?? $this->determinePageId()) ?: [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a TypoScript condition given as input, eg. "[browser=net][...(other conditions)...]"
|
||||
*
|
||||
* @param string $string The condition to match against its criteria.
|
||||
* @return bool Whether the condition matched
|
||||
* @see \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser::parse()
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function evaluateCondition($string)
|
||||
{
|
||||
if ($this->strictSyntaxEnabled()) {
|
||||
trigger_error('The old condition syntax will be removed in TYPO3 v10.0, use the new expression language. Used condition: [' . $string . '].', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
list($key, $value) = GeneralUtility::trimExplode('=', $string, false, 2);
|
||||
$result = $this->evaluateConditionCommon($key, $value);
|
||||
if (is_bool($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
switch ($key) {
|
||||
case 'usergroup':
|
||||
$groupList = $this->getGroupList();
|
||||
$values = GeneralUtility::trimExplode(',', $value, true);
|
||||
foreach ($values as $test) {
|
||||
if ($test === '*' || GeneralUtility::inList($groupList, $test)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'adminUser':
|
||||
if ($this->isUserLoggedIn()) {
|
||||
return !((bool)$value xor $this->isAdminUser());
|
||||
}
|
||||
break;
|
||||
case 'treeLevel':
|
||||
$values = GeneralUtility::trimExplode(',', $value, true);
|
||||
$treeLevel = count($this->rootline) - 1;
|
||||
// If a new page is being edited or saved the treeLevel is higher by one:
|
||||
if ($this->isNewPageWithPageId($this->pageId)) {
|
||||
$treeLevel++;
|
||||
}
|
||||
foreach ($values as $test) {
|
||||
if ($test == $treeLevel) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'PIDupinRootline':
|
||||
case 'PIDinRootline':
|
||||
$values = GeneralUtility::trimExplode(',', $value, true);
|
||||
if ($key === 'PIDinRootline' || !in_array($this->pageId, $values) || $this->isNewPageWithPageId($this->pageId)) {
|
||||
foreach ($values as $test) {
|
||||
foreach ($this->rootline as $rl_dat) {
|
||||
if ($rl_dat['uid'] == $test) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$conditionResult = $this->evaluateCustomDefinedCondition($string);
|
||||
if ($conditionResult !== null) {
|
||||
return $conditionResult;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns GP / ENV vars
|
||||
*
|
||||
* @param string $var Identifier
|
||||
* @return mixed The value of the variable pointed to or NULL if variable did not exist
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function getVariable($var)
|
||||
{
|
||||
$vars = explode(':', $var, 2);
|
||||
return $this->getVariableCommon($vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the usergroup list of the current user.
|
||||
*
|
||||
* @return string The usergroup list of the current user
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function getGroupList()
|
||||
{
|
||||
return $this->getBackendUserAuthentication()->groupList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to determine the ID of the page currently processed.
|
||||
* When User/Group TS-Config is parsed when no specific page is handled
|
||||
* (i.e. in the Extension Manager, etc.) this function will return "0", so that
|
||||
* the accordant conditions (e.g. PIDinRootline) will return "FALSE"
|
||||
*
|
||||
* @return int The determined page id or otherwise 0
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function determinePageId()
|
||||
{
|
||||
$pageId = 0;
|
||||
$editStatement = GeneralUtility::_GP('edit');
|
||||
$commandStatement = GeneralUtility::_GP('cmd');
|
||||
// Determine id from module that was called with an id:
|
||||
if ($id = (int)GeneralUtility::_GP('id')) {
|
||||
$pageId = $id;
|
||||
} elseif (is_array($editStatement)) {
|
||||
$table = key($editStatement);
|
||||
$uidAndAction = current($editStatement);
|
||||
$uid = key($uidAndAction);
|
||||
$action = current($uidAndAction);
|
||||
if ($action === 'edit') {
|
||||
$pageId = $this->getPageIdByRecord($table, $uid);
|
||||
} elseif ($action === 'new') {
|
||||
$pageId = $this->getPageIdByRecord($table, $uid, true);
|
||||
}
|
||||
} elseif (is_array($commandStatement)) {
|
||||
$table = key($commandStatement);
|
||||
$uidActionAndTarget = current($commandStatement);
|
||||
$uid = key($uidActionAndTarget);
|
||||
$actionAndTarget = current($uidActionAndTarget);
|
||||
$action = key($actionAndTarget);
|
||||
$target = current($actionAndTarget);
|
||||
if ($action === 'delete') {
|
||||
$pageId = $this->getPageIdByRecord($table, $uid);
|
||||
} elseif ($action === 'copy' || $action === 'move') {
|
||||
$pageId = $this->getPageIdByRecord($table, $target, true);
|
||||
}
|
||||
}
|
||||
return $pageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the properties for the current page.
|
||||
*
|
||||
* @return array The properties for the current page.
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function getPage()
|
||||
{
|
||||
$pageId = $this->pageId ?? $this->determinePageId();
|
||||
return BackendUtility::getRecord('pages', $pageId) ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the page id by a record.
|
||||
*
|
||||
* @param string $table Name of the table
|
||||
* @param int $id Id of the accordant record
|
||||
* @param bool $ignoreTable Whether to ignore the page, if TRUE a positive
|
||||
* @return int Id of the page the record is persisted on
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function getPageIdByRecord($table, $id, $ignoreTable = false)
|
||||
{
|
||||
$pageId = 0;
|
||||
$id = (int)$id;
|
||||
if ($table && $id) {
|
||||
if (($ignoreTable || $table === 'pages') && $id >= 0) {
|
||||
$pageId = $id;
|
||||
} else {
|
||||
$record = BackendUtility::getRecordWSOL($table, abs($id), '*', '', false);
|
||||
$pageId = $record['pid'];
|
||||
}
|
||||
}
|
||||
return $pageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if record of table 'pages' with the given $pid is currently created in TCEforms.
|
||||
* This information is required for conditions in BE for PIDupinRootline.
|
||||
*
|
||||
* @param int $pageId The pid the check for as parent page
|
||||
* @return bool TRUE if the is currently a new page record being edited with $pid as uid of the parent page
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function isNewPageWithPageId($pageId)
|
||||
{
|
||||
if (isset($GLOBALS['SOBE']) && $GLOBALS['SOBE'] instanceof EditDocumentController) {
|
||||
$pageId = (int)$pageId;
|
||||
$elementsData = $GLOBALS['SOBE']->elementsData;
|
||||
$data = $GLOBALS['SOBE']->data;
|
||||
// If saving a new page record:
|
||||
if (is_array($data) && isset($data['pages']) && is_array($data['pages'])) {
|
||||
foreach ($data['pages'] as $uid => $fields) {
|
||||
if (strpos($uid, 'NEW') === 0 && $fields['pid'] == $pageId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If editing a new page record (not saved yet):
|
||||
if (is_array($elementsData)) {
|
||||
foreach ($elementsData as $element) {
|
||||
if ($element['cmd'] === 'new' && $element['table'] === 'pages') {
|
||||
if ($element['pid'] < 0) {
|
||||
$pageRecord = BackendUtility::getRecord('pages', abs($element['pid']), 'pid');
|
||||
$element['pid'] = $pageRecord['pid'];
|
||||
}
|
||||
if ($element['pid'] == $pageId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the rootline for the current page.
|
||||
*
|
||||
* @return array The rootline for the current page.
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function determineRootline()
|
||||
{
|
||||
$pageId = $this->pageId ?? $this->determinePageId();
|
||||
return BackendUtility::BEgetRootLine($pageId, '', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the id of the current user.
|
||||
*
|
||||
* @return int The id of the current user
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function getUserId()
|
||||
{
|
||||
return $this->getBackendUserAuthentication()->user['uid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a user is logged in.
|
||||
*
|
||||
* @return bool Determines if a user is logged in
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function isUserLoggedIn()
|
||||
{
|
||||
return (bool)$this->getBackendUserAuthentication()->user['uid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the current user is admin.
|
||||
*
|
||||
* @return bool Whether the current user is admin
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function isAdminUser()
|
||||
{
|
||||
return $this->getBackendUserAuthentication()->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
|
||||
* @deprecated since TYPO3 v9.4, will be removed in TYPO3 v10.0.
|
||||
*/
|
||||
protected function getBackendUserAuthentication()
|
||||
{
|
||||
return $GLOBALS['BE_USER'] ?? null;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user