first commit

This commit is contained in:
salam committed 2026-10-19 08:18:39 +02:00
commit 1218dd1517
12716 files changed
+989233

No files matched your search

@@ -0,0 +1,311 @@
<?php
namespace TYPO3\CMS\Extbase\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!
*/
/**
* Abstract base class for a general purpose configuration manager
* @internal only to be used within Extbase, not part of TYPO3 Core API.
*/
abstract class AbstractConfigurationManager implements \TYPO3\CMS\Core\SingletonInterface
{
/**
* Default backend storage PID
*/
const DEFAULT_BACKEND_STORAGE_PID = 0;
/**
* Storage of the raw TypoScript configuration
*
* @var array
*/
protected $configuration = [];
/**
* @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
*/
protected $contentObject;
/**
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
*/
protected $objectManager;
/**
* @var \TYPO3\CMS\Core\TypoScript\TypoScriptService
*/
protected $typoScriptService;
/**
* name of the extension this Configuration Manager instance belongs to
*
* @var string
*/
protected $extensionName;
/**
* name of the plugin this Configuration Manager instance belongs to
*
* @var string
*/
protected $pluginName;
/**
* 1st level configuration cache
*
* @var array
*/
protected $configurationCache = [];
/**
* @var \TYPO3\CMS\Extbase\Service\EnvironmentService
*/
protected $environmentService;
/**
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
*/
public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
{
$this->objectManager = $objectManager;
}
/**
* @param \TYPO3\CMS\Core\TypoScript\TypoScriptService $typoScriptService
*/
public function injectTypoScriptService(\TYPO3\CMS\Core\TypoScript\TypoScriptService $typoScriptService)
{
$this->typoScriptService = $typoScriptService;
}
/**
* @param \TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService
*/
public function injectEnvironmentService(\TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService)
{
$this->environmentService = $environmentService;
}
/**
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject
*/
public function setContentObject(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject = null)
{
$this->contentObject = $contentObject;
}
/**
* @return \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer|null
*/
public function getContentObject()
{
if ($this->contentObject !== null) {
return $this->contentObject;
}
return null;
}
/**
* Sets the specified raw configuration coming from the outside.
* Note that this is a low level method and only makes sense to be used by Extbase internally.
*
* @param array $configuration The new configuration
*/
public function setConfiguration(array $configuration = [])
{
// reset 1st level cache
$this->configurationCache = [];
$this->extensionName = $configuration['extensionName'] ?? null;
$this->pluginName = $configuration['pluginName'] ?? null;
$this->configuration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($configuration);
}
/**
* Loads the Extbase Framework configuration.
*
* The Extbase framework configuration HAS TO be retrieved using this method, as they are come from different places than the normal settings.
* Framework configuration is, in contrast to normal settings, needed for the Extbase framework to operate correctly.
*
* @param string $extensionName if specified, the configuration for the given extension will be returned (plugin.tx_extensionname)
* @param string $pluginName if specified, the configuration for the given plugin will be returned (plugin.tx_extensionname_pluginname)
* @return array the Extbase framework configuration
*/
public function getConfiguration($extensionName = null, $pluginName = null)
{
// 1st level cache
$configurationCacheKey = strtolower(($extensionName ?: $this->extensionName) . '_' . ($pluginName ?: $this->pluginName));
if (isset($this->configurationCache[$configurationCacheKey])) {
return $this->configurationCache[$configurationCacheKey];
}
$frameworkConfiguration = $this->getExtbaseConfiguration();
if (!isset($frameworkConfiguration['persistence']['storagePid'])) {
$frameworkConfiguration['persistence']['storagePid'] = $this->getDefaultBackendStoragePid();
}
// only merge $this->configuration and override switchableControllerActions when retrieving configuration of the current plugin
if ($extensionName === null || $extensionName === $this->extensionName && $pluginName === $this->pluginName) {
$pluginConfiguration = $this->getPluginConfiguration($this->extensionName, $this->pluginName);
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($pluginConfiguration, $this->configuration);
$pluginConfiguration['controllerConfiguration'] = $this->getSwitchableControllerActions($this->extensionName, $this->pluginName);
if (isset($this->configuration['switchableControllerActions'])) {
$this->overrideSwitchableControllerActions($pluginConfiguration, $this->configuration['switchableControllerActions']);
}
} else {
$pluginConfiguration = $this->getPluginConfiguration($extensionName, $pluginName);
$pluginConfiguration['controllerConfiguration'] = $this->getSwitchableControllerActions($extensionName, $pluginName);
}
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($frameworkConfiguration, $pluginConfiguration);
// only load context specific configuration when retrieving configuration of the current plugin
if ($extensionName === null || $extensionName === $this->extensionName && $pluginName === $this->pluginName) {
$frameworkConfiguration = $this->getContextSpecificFrameworkConfiguration($frameworkConfiguration);
}
if (!empty($frameworkConfiguration['persistence']['storagePid'])) {
if (is_array($frameworkConfiguration['persistence']['storagePid'])) {
// We simulate the frontend to enable the use of cObjects in
// stdWrap. Than we convert the configuration to normal TypoScript
// and apply the stdWrap to the storagePid
if (!$this->environmentService->isEnvironmentInFrontendMode()) {
\TYPO3\CMS\Extbase\Utility\FrontendSimulatorUtility::simulateFrontendEnvironment($this->getContentObject());
}
$conf = $this->typoScriptService->convertPlainArrayToTypoScriptArray($frameworkConfiguration['persistence']);
$frameworkConfiguration['persistence']['storagePid'] = $GLOBALS['TSFE']->cObj->stdWrap($conf['storagePid'], $conf['storagePid.']);
if (!$this->environmentService->isEnvironmentInFrontendMode()) {
\TYPO3\CMS\Extbase\Utility\FrontendSimulatorUtility::resetFrontendEnvironment();
}
}
if (!empty($frameworkConfiguration['persistence']['recursive'])) {
// All implementations of getTreeList allow to pass the ids negative to include them into the result
// otherwise only childpages are returned
$storagePids = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $frameworkConfiguration['persistence']['storagePid']);
array_walk($storagePids, function (&$storagePid) {
if ($storagePid > 0) {
$storagePid = -$storagePid;
}
});
$frameworkConfiguration['persistence']['storagePid'] = $this->getRecursiveStoragePids(
implode(',', $storagePids),
(int)$frameworkConfiguration['persistence']['recursive']
);
}
}
// 1st level cache
$this->configurationCache[$configurationCacheKey] = $frameworkConfiguration;
return $frameworkConfiguration;
}
/**
* Returns the TypoScript configuration found in config.tx_extbase
*
* @return array
*/
protected function getExtbaseConfiguration()
{
$setup = $this->getTypoScriptSetup();
$extbaseConfiguration = [];
if (isset($setup['config.']['tx_extbase.'])) {
$extbaseConfiguration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($setup['config.']['tx_extbase.']);
}
return $extbaseConfiguration;
}
/**
* Returns the default backend storage pid
*
* @return string
*/
public function getDefaultBackendStoragePid()
{
return self::DEFAULT_BACKEND_STORAGE_PID;
}
/**
* @param array &$frameworkConfiguration
* @param array $switchableControllerActions
*/
protected function overrideSwitchableControllerActions(array &$frameworkConfiguration, array $switchableControllerActions)
{
$overriddenSwitchableControllerActions = [];
foreach ($switchableControllerActions as $controllerName => $actions) {
if (!isset($frameworkConfiguration['controllerConfiguration'][$controllerName])) {
continue;
}
$overriddenSwitchableControllerActions[$controllerName] = ['actions' => $actions];
$nonCacheableActions = $frameworkConfiguration['controllerConfiguration'][$controllerName]['nonCacheableActions'] ?? null;
if (!is_array($nonCacheableActions)) {
// There are no non-cacheable actions, thus we can directly continue
// with the next controller name.
continue;
}
$overriddenNonCacheableActions = array_intersect($nonCacheableActions, $actions);
if (!empty($overriddenNonCacheableActions)) {
$overriddenSwitchableControllerActions[$controllerName]['nonCacheableActions'] = $overriddenNonCacheableActions;
}
}
$frameworkConfiguration['controllerConfiguration'] = $overriddenSwitchableControllerActions;
}
/**
* The context specific configuration returned by this method
* will override the framework configuration which was
* obtained from TypoScript. This can be used f.e. to override the storagePid
* with the value set inside the Plugin Instance.
*
* WARNING: Make sure this method ALWAYS returns an array!
*
* @param array $frameworkConfiguration The framework configuration until now
* @return array context specific configuration which will override the configuration obtained by TypoScript
*/
abstract protected function getContextSpecificFrameworkConfiguration(array $frameworkConfiguration);
/**
* Returns TypoScript Setup array from current Environment.
*
* @return array the TypoScript setup
*/
abstract public function getTypoScriptSetup();
/**
* Returns the TypoScript configuration found in plugin.tx_yourextension_yourplugin / module.tx_yourextension_yourmodule
* merged with the global configuration of your extension from plugin.tx_yourextension / module.tx_yourextension
*
* @param string $extensionName
* @param string $pluginName in FE mode this is the specified plugin name, in BE mode this is the full module signature
* @return array
*/
abstract protected function getPluginConfiguration($extensionName, $pluginName = null);
/**
* Returns the configured controller/action pairs of the specified plugin/module in the format
* array(
* 'Controller1' => array('action1', 'action2'),
* 'Controller2' => array('action3', 'action4')
* )
*
* @param string $extensionName
* @param string $pluginName in FE mode this is the specified plugin name, in BE mode this is the full module signature
* @return array
*/
abstract protected function getSwitchableControllerActions($extensionName, $pluginName);
/**
* The implementation of the methods to return a list of storagePid that are below a certain
* storage pid.
*
* @param string $storagePid Storage PID to start at; multiple PIDs possible as comma-separated list
* @param int $recursionDepth Maximum number of levels to search, 0 to disable recursive lookup
* @return string storage PIDs
*/
abstract protected function getRecursiveStoragePids($storagePid, $recursionDepth = 0);
}
@@ -0,0 +1,283 @@
<?php
namespace TYPO3\CMS\Extbase\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\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
use TYPO3\CMS\Core\Database\QueryGenerator;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\TypoScript\TemplateService;
use TYPO3\CMS\Core\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\RootlineUtility;
use TYPO3\CMS\Extbase\Mvc\Web\BackendRequestHandler;
use TYPO3\CMS\Extbase\Mvc\Web\FrontendRequestHandler;
/**
* A general purpose configuration manager used in backend mode.
* @internal only to be used within Extbase, not part of TYPO3 Core API.
*/
class BackendConfigurationManager extends AbstractConfigurationManager
{
/**
* @var array
*/
protected $typoScriptSetupCache = [];
/**
* stores the current page ID
* @var int
*/
protected $currentPageId;
/**
* Returns TypoScript Setup array from current Environment.
*
* @return array the raw TypoScript setup
*/
public function getTypoScriptSetup()
{
$pageId = $this->getCurrentPageId();
if (!array_key_exists($pageId, $this->typoScriptSetupCache)) {
/** @var TemplateService $template */
$template = GeneralUtility::makeInstance(TemplateService::class);
// do not log time-performance information
$template->tt_track = false;
// Explicitly trigger processing of extension static files
$template->setProcessExtensionStatics(true);
// Get the root line
$rootline = [];
if ($pageId > 0) {
try {
$rootline = GeneralUtility::makeInstance(RootlineUtility::class, $pageId)->get();
} catch (\RuntimeException $e) {
$rootline = [];
}
}
// This generates the constants/config + hierarchy info for the template.
$template->runThroughTemplates($rootline, 0);
$template->generateConfig();
$this->typoScriptSetupCache[$pageId] = $template->setup;
}
return $this->typoScriptSetupCache[$pageId];
}
/**
* Returns the TypoScript configuration found in module.tx_yourextension_yourmodule
* merged with the global configuration of your extension from module.tx_yourextension
*
* @param string $extensionName
* @param string $pluginName in BE mode this is actually the module signature. But we're using it just like the plugin name in FE
* @return array
*/
protected function getPluginConfiguration($extensionName, $pluginName = null)
{
$setup = $this->getTypoScriptSetup();
$pluginConfiguration = [];
if (is_array($setup['module.']['tx_' . strtolower($extensionName) . '.'] ?? false)) {
$pluginConfiguration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($setup['module.']['tx_' . strtolower($extensionName) . '.']);
}
if ($pluginName !== null) {
$pluginSignature = strtolower($extensionName . '_' . $pluginName);
if (is_array($setup['module.']['tx_' . $pluginSignature . '.'] ?? false)) {
$overruleConfiguration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($setup['module.']['tx_' . $pluginSignature . '.']);
ArrayUtility::mergeRecursiveWithOverrule($pluginConfiguration, $overruleConfiguration);
}
}
return $pluginConfiguration;
}
/**
* Returns the configured controller/action pairs of the specified module in the format
* array(
* 'Controller1' => array('action1', 'action2'),
* 'Controller2' => array('action3', 'action4')
* )
*
* @param string $extensionName
* @param string $pluginName in BE mode this is actually the module signature. But we're using it just like the plugin name in FE
* @return array
*/
protected function getSwitchableControllerActions($extensionName, $pluginName)
{
$switchableControllerActions = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['modules'][$pluginName]['controllers'] ?? false;
if (!is_array($switchableControllerActions)) {
$switchableControllerActions = [];
}
return $switchableControllerActions;
}
/**
* Returns the page uid of the current page.
* If no page is selected, we'll return the uid of the first root page.
*
* @return int current page id. If no page is selected current root page id is returned
*/
protected function getCurrentPageId()
{
if ($this->currentPageId !== null) {
return $this->currentPageId;
}
$this->currentPageId = $this->getCurrentPageIdFromGetPostData() ?: $this->getCurrentPageIdFromCurrentSiteRoot();
$this->currentPageId = $this->currentPageId ?: $this->getCurrentPageIdFromRootTemplate();
$this->currentPageId = $this->currentPageId ?: self::DEFAULT_BACKEND_STORAGE_PID;
return $this->currentPageId;
}
/**
* Gets the current page ID from the GET/POST data.
*
* @return int the page UID, will be 0 if none has been set
*/
protected function getCurrentPageIdFromGetPostData()
{
return (int)GeneralUtility::_GP('id');
}
/**
* Gets the current page ID from the first site root in tree.
*
* @return int the page UID, will be 0 if none has been set
*/
protected function getCurrentPageIdFromCurrentSiteRoot()
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$queryBuilder
->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(HiddenRestriction::class));
$rootPage = $queryBuilder
->select('uid')
->from('pages')
->where(
$queryBuilder->expr()->eq('is_siteroot', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT)),
$queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
)
->orderBy('sorting')
->execute()
->fetch();
if (empty($rootPage)) {
return 0;
}
return (int)$rootPage['uid'];
}
/**
* Gets the current page ID from the first created root template.
*
* @return int the page UID, will be 0 if none has been set
*/
protected function getCurrentPageIdFromRootTemplate()
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('sys_template');
$queryBuilder
->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(HiddenRestriction::class));
$rootTemplate = $queryBuilder
->select('pid')
->from('sys_template')
->where(
$queryBuilder->expr()->eq('root', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
)
->orderBy('crdate')
->execute()
->fetch();
if (empty($rootTemplate)) {
return 0;
}
return (int)$rootTemplate['pid'];
}
/**
* Returns the default backend storage pid
*
* @return string
*/
public function getDefaultBackendStoragePid()
{
return $this->getCurrentPageId();
}
/**
* We need to set some default request handler if the framework configuration
* could not be loaded; to make sure Extbase also works in Backend modules
* in all contexts.
*
* @param array $frameworkConfiguration
* @return array
*/
protected function getContextSpecificFrameworkConfiguration(array $frameworkConfiguration)
{
if (!isset($frameworkConfiguration['mvc']['requestHandlers'])) {
$frameworkConfiguration['mvc']['requestHandlers'] = [
FrontendRequestHandler::class => FrontendRequestHandler::class,
BackendRequestHandler::class => BackendRequestHandler::class
];
}
return $frameworkConfiguration;
}
/**
* Returns a comma separated list of storagePid that are below a certain storage pid.
*
* @param string $storagePid Storage PID to start at; multiple PIDs possible as comma-separated list
* @param int $recursionDepth Maximum number of levels to search, 0 to disable recursive lookup
* @return string storage PIDs
*/
protected function getRecursiveStoragePids($storagePid, $recursionDepth = 0)
{
if ($recursionDepth <= 0) {
return $storagePid;
}
$recursiveStoragePids = '';
$storagePids = GeneralUtility::intExplode(',', $storagePid);
$permsClause = $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW);
$queryGenerator = GeneralUtility::makeInstance(QueryGenerator::class);
foreach ($storagePids as $startPid) {
$pids = $queryGenerator->getTreeList($startPid, $recursionDepth, 0, $permsClause);
if ((string)$pids !== '') {
$recursiveStoragePids .= $pids . ',';
}
}
return rtrim($recursiveStoragePids, ',');
}
/**
* @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
*/
protected function getBackendUser()
{
return $GLOBALS['BE_USER'];
}
}
@@ -0,0 +1,150 @@
<?php
namespace TYPO3\CMS\Extbase\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!
*/
/**
* A configuration manager following the strategy pattern (GoF315). It hides the concrete
* implementation of the configuration manager and provides an unified acccess point.
*
* Use the shutdown() method to drop the concrete implementation.
* @internal only to be used within Extbase, not part of TYPO3 Core API.
*/
class ConfigurationManager implements \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
{
/**
* @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
*/
protected $objectManager;
/**
* @var \TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager
*/
protected $concreteConfigurationManager;
/**
* @var \TYPO3\CMS\Extbase\Service\EnvironmentService
*/
protected $environmentService;
/**
* @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
*/
public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
{
$this->objectManager = $objectManager;
}
/**
* @param \TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService
*/
public function injectEnvironmentService(\TYPO3\CMS\Extbase\Service\EnvironmentService $environmentService)
{
$this->environmentService = $environmentService;
}
/**
* Initializes the object
*/
public function initializeObject()
{
$this->initializeConcreteConfigurationManager();
}
/**
*/
protected function initializeConcreteConfigurationManager()
{
if ($this->environmentService->isEnvironmentInFrontendMode()) {
$this->concreteConfigurationManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Configuration\FrontendConfigurationManager::class);
} else {
$this->concreteConfigurationManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager::class);
}
}
/**
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject
*/
public function setContentObject(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject = null)
{
$this->concreteConfigurationManager->setContentObject($contentObject);
}
/**
* @return \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
*/
public function getContentObject()
{
return $this->concreteConfigurationManager->getContentObject();
}
/**
* Sets the specified raw configuration coming from the outside.
* Note that this is a low level method and only makes sense to be used by Extbase internally.
*
* @param array $configuration The new configuration
*/
public function setConfiguration(array $configuration = [])
{
$this->concreteConfigurationManager->setConfiguration($configuration);
}
/**
* Returns the specified configuration.
* The actual configuration will be merged from different sources in a defined order.
*
* You can get the following types of configuration invoking:
* CONFIGURATION_TYPE_SETTINGS: Extbase settings
* CONFIGURATION_TYPE_FRAMEWORK: the current module/plugin settings
* CONFIGURATION_TYPE_FULL_TYPOSCRIPT: a raw TS array
*
* Note that this is a low level method and only makes sense to be used by Extbase internally.
*
* @param string $configurationType The kind of configuration to fetch - must be one of the CONFIGURATION_TYPE_* constants
* @param string $extensionName if specified, the configuration for the given extension will be returned.
* @param string $pluginName if specified, the configuration for the given plugin will be returned.
* @throws Exception\InvalidConfigurationTypeException
* @return array The configuration
*/
public function getConfiguration($configurationType, $extensionName = null, $pluginName = null)
{
switch ($configurationType) {
case self::CONFIGURATION_TYPE_SETTINGS:
$configuration = $this->concreteConfigurationManager->getConfiguration($extensionName, $pluginName);
return $configuration['settings'] ?? [];
case self::CONFIGURATION_TYPE_FRAMEWORK:
return $this->concreteConfigurationManager->getConfiguration($extensionName, $pluginName);
case self::CONFIGURATION_TYPE_FULL_TYPOSCRIPT:
return $this->concreteConfigurationManager->getTypoScriptSetup();
default:
throw new \TYPO3\CMS\Extbase\Configuration\Exception\InvalidConfigurationTypeException('Invalid configuration type "' . $configurationType . '"', 1206031879);
}
}
/**
* Returns TRUE if a certain feature, identified by $featureName
* should be activated, FALSE for backwards-compatible behavior.
*
* This is an INTERNAL API used throughout Extbase and Fluid for providing backwards-compatibility.
* Do not use it in your custom code!
*
* @param string $featureName
* @return bool
*/
public function isFeatureEnabled($featureName)
{
$configuration = $this->getConfiguration(self::CONFIGURATION_TYPE_FRAMEWORK);
return (bool)(isset($configuration['features'][$featureName]) && $configuration['features'][$featureName]);
}
}
@@ -0,0 +1,71 @@
<?php
namespace TYPO3\CMS\Extbase\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!
*/
/**
* Class ConfigurationManagerInterface
* @internal only to be used within Extbase, not part of TYPO3 Core API.
*/
interface ConfigurationManagerInterface extends \TYPO3\CMS\Core\SingletonInterface
{
const CONFIGURATION_TYPE_FRAMEWORK = 'Framework';
const CONFIGURATION_TYPE_SETTINGS = 'Settings';
const CONFIGURATION_TYPE_FULL_TYPOSCRIPT = 'FullTypoScript';
/**
* @param \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject
*/
public function setContentObject(\TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer $contentObject = null);
/**
* Get the content object
*
* @return \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
*/
public function getContentObject();
/**
* Returns the specified configuration.
* The actual configuration will be merged from different sources in a defined order.
*
* Note that this is a low level method and only makes sense to be used by Extbase internally.
*
* @param string $configurationType The kind of configuration to fetch - must be one of the CONFIGURATION_TYPE_* constants
* @param string $extensionName if specified, the configuration for the given extension will be returned.
* @param string $pluginName if specified, the configuration for the given plugin will be returned.
* @return array The configuration
*/
public function getConfiguration($configurationType, $extensionName = null, $pluginName = null);
/**
* Sets the specified raw configuration coming from the outside.
* Note that this is a low level method and only makes sense to be used by Extbase internally.
*
* @param array $configuration The new configuration
*/
public function setConfiguration(array $configuration = []);
/**
* Returns TRUE if a certain feature, identified by $featureName
* should be activated, FALSE for backwards-compatible behavior.
*
* This is an INTERNAL API used throughout Extbase and Fluid for providing backwards-compatibility.
* Do not use it in your custom code!
*
* @param string $featureName
* @return bool
*/
public function isFeatureEnabled($featureName);
}
@@ -0,0 +1,22 @@
<?php
namespace TYPO3\CMS\Extbase\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!
*/
/**
* A generic Configuration Exception
*/
class Exception extends \TYPO3\CMS\Extbase\Exception
{
}
@@ -0,0 +1,22 @@
<?php
namespace TYPO3\CMS\Extbase\Configuration\Exception;
/*
* 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!
*/
/**
* An Invalid Configuration Type Exception
*/
class InvalidConfigurationTypeException extends \TYPO3\CMS\Extbase\Configuration\Exception
{
}
@@ -0,0 +1,22 @@
<?php
namespace TYPO3\CMS\Extbase\Configuration\Exception;
/*
* 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!
*/
/**
* A Parse Error exception
*/
class ParseErrorException extends \TYPO3\CMS\Extbase\Configuration\Exception
{
}
@@ -0,0 +1,266 @@
<?php
namespace TYPO3\CMS\Extbase\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\Utility\ArrayUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* A general purpose configuration manager used in frontend mode.
*
* Should NOT be singleton, as a new configuration manager is needed per plugin.
* @internal only to be used within Extbase, not part of TYPO3 Core API.
*/
class FrontendConfigurationManager extends \TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager
{
/**
* @var \TYPO3\CMS\Core\Service\FlexFormService
*/
protected $flexFormService;
/**
* @param \TYPO3\CMS\Core\Service\FlexFormService $flexFormService
*/
public function injectFlexFormService(\TYPO3\CMS\Core\Service\FlexFormService $flexFormService)
{
$this->flexFormService = $flexFormService;
}
/**
* Returns TypoScript Setup array from current Environment.
*
* @return array the raw TypoScript setup
*/
public function getTypoScriptSetup()
{
return $GLOBALS['TSFE']->tmpl->setup;
}
/**
* Returns the TypoScript configuration found in plugin.tx_yourextension_yourplugin
* merged with the global configuration of your extension from plugin.tx_yourextension
*
* @param string $extensionName
* @param string $pluginName
* @return array
*/
protected function getPluginConfiguration($extensionName, $pluginName = null)
{
$setup = $this->getTypoScriptSetup();
$pluginConfiguration = [];
if (isset($setup['plugin.']['tx_' . strtolower($extensionName) . '.']) && is_array($setup['plugin.']['tx_' . strtolower($extensionName) . '.'])) {
$pluginConfiguration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($setup['plugin.']['tx_' . strtolower($extensionName) . '.']);
}
if ($pluginName !== null) {
$pluginSignature = strtolower($extensionName . '_' . $pluginName);
if (isset($setup['plugin.']['tx_' . $pluginSignature . '.']) && is_array($setup['plugin.']['tx_' . $pluginSignature . '.'])) {
ArrayUtility::mergeRecursiveWithOverrule(
$pluginConfiguration,
$this->typoScriptService->convertTypoScriptArrayToPlainArray($setup['plugin.']['tx_' . $pluginSignature . '.'])
);
}
}
return $pluginConfiguration;
}
/**
* Returns the configured controller/action pairs of the specified plugin in the format
* array(
* 'Controller1' => array('action1', 'action2'),
* 'Controller2' => array('action3', 'action4')
* )
*
* @param string $extensionName
* @param string $pluginName
* @return array
*/
protected function getSwitchableControllerActions($extensionName, $pluginName)
{
$switchableControllerActions = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'] ?? [];
if (!is_array($switchableControllerActions)) {
$switchableControllerActions = [];
}
return $switchableControllerActions;
}
/**
* Get context specific framework configuration.
* - Overrides storage PID with setting "Startingpoint"
* - merge flexForm configuration, if needed
*
* @param array $frameworkConfiguration The framework configuration to modify
* @return array the modified framework configuration
*/
protected function getContextSpecificFrameworkConfiguration(array $frameworkConfiguration)
{
$frameworkConfiguration = $this->overrideStoragePidIfStartingPointIsSet($frameworkConfiguration);
$frameworkConfiguration = $this->overrideConfigurationFromPlugin($frameworkConfiguration);
$frameworkConfiguration = $this->overrideConfigurationFromFlexForm($frameworkConfiguration);
return $frameworkConfiguration;
}
/**
* Overrides the storage PID settings, in case the "Startingpoint" settings
* is set in the plugin configuration.
*
* @param array $frameworkConfiguration the framework configurations
* @return array the framework configuration with overridden storagePid
*/
protected function overrideStoragePidIfStartingPointIsSet(array $frameworkConfiguration)
{
$pages = $this->contentObject->data['pages'];
if (is_string($pages) && $pages !== '') {
$list = [];
if ($this->contentObject->data['recursive'] > 0) {
$explodedPages = GeneralUtility::trimExplode(',', $pages);
foreach ($explodedPages as $pid) {
$pids = $this->contentObject->getTreeList($pid, $this->contentObject->data['recursive']);
if ($pids !== '') {
$list[] = $pids;
}
}
}
if (!empty($list)) {
$pages = $pages . ',' . implode(',', $list);
}
ArrayUtility::mergeRecursiveWithOverrule($frameworkConfiguration, [
'persistence' => [
'storagePid' => $pages
]
]);
}
return $frameworkConfiguration;
}
/**
* Overrides configuration settings from the plugin typoscript (plugin.tx_myext_pi1.)
*
* @param array $frameworkConfiguration the framework configuration
* @return array the framework configuration with overridden data from typoscript
*/
protected function overrideConfigurationFromPlugin(array $frameworkConfiguration)
{
$setup = $this->getTypoScriptSetup();
$pluginSignature = strtolower($frameworkConfiguration['extensionName'] . '_' . $frameworkConfiguration['pluginName']);
$pluginConfiguration = $setup['plugin.']['tx_' . $pluginSignature . '.'];
if (is_array($pluginConfiguration)) {
$pluginConfiguration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($pluginConfiguration);
$frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $pluginConfiguration, 'settings');
$frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $pluginConfiguration, 'persistence');
$frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $pluginConfiguration, 'view');
}
return $frameworkConfiguration;
}
/**
* Overrides configuration settings from flexForms.
* This merges the whole flexForm data, and overrides switchable controller actions.
*
* @param array $frameworkConfiguration the framework configuration
* @return array the framework configuration with overridden data from flexForm
*/
protected function overrideConfigurationFromFlexForm(array $frameworkConfiguration)
{
$flexFormConfiguration = $this->contentObject->data['pi_flexform'];
if (is_string($flexFormConfiguration)) {
if ($flexFormConfiguration !== '') {
$flexFormConfiguration = $this->flexFormService->convertFlexFormContentToArray($flexFormConfiguration);
} else {
$flexFormConfiguration = [];
}
}
if (is_array($flexFormConfiguration) && !empty($flexFormConfiguration)) {
$frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $flexFormConfiguration, 'settings');
$frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $flexFormConfiguration, 'persistence');
$frameworkConfiguration = $this->mergeConfigurationIntoFrameworkConfiguration($frameworkConfiguration, $flexFormConfiguration, 'view');
$frameworkConfiguration = $this->overrideSwitchableControllerActionsFromFlexForm($frameworkConfiguration, $flexFormConfiguration);
}
return $frameworkConfiguration;
}
/**
* Merge a configuration into the framework configuration.
*
* @param array $frameworkConfiguration the framework configuration to merge the data on
* @param array $configuration The configuration
* @param string $configurationPartName The name of the configuration part which should be merged.
* @return array the processed framework configuration
*/
protected function mergeConfigurationIntoFrameworkConfiguration(array $frameworkConfiguration, array $configuration, $configurationPartName)
{
if (isset($configuration[$configurationPartName]) && is_array($configuration[$configurationPartName])) {
if (isset($frameworkConfiguration[$configurationPartName]) && is_array($frameworkConfiguration[$configurationPartName])) {
ArrayUtility::mergeRecursiveWithOverrule($frameworkConfiguration[$configurationPartName], $configuration[$configurationPartName]);
} else {
$frameworkConfiguration[$configurationPartName] = $configuration[$configurationPartName];
}
}
return $frameworkConfiguration;
}
/**
* Overrides the switchable controller actions from the flexForm.
*
* @param array $frameworkConfiguration The original framework configuration
* @param array $flexFormConfiguration The full flexForm configuration
* @throws Exception\ParseErrorException
* @return array the modified framework configuration, if needed
*/
protected function overrideSwitchableControllerActionsFromFlexForm(array $frameworkConfiguration, array $flexFormConfiguration)
{
if (!isset($flexFormConfiguration['switchableControllerActions']) || is_array($flexFormConfiguration['switchableControllerActions'])) {
return $frameworkConfiguration;
}
// As "," is the flexForm field value delimiter, we need to use ";" as in-field delimiter. That's why we need to replace ; by , first.
// The expected format is: "Controller1->action2;Controller2->action3;Controller2->action1"
$switchableControllerActionPartsFromFlexForm = GeneralUtility::trimExplode(',', str_replace(';', ',', $flexFormConfiguration['switchableControllerActions']), true);
$newSwitchableControllerActionsFromFlexForm = [];
foreach ($switchableControllerActionPartsFromFlexForm as $switchableControllerActionPartFromFlexForm) {
list($controller, $action) = GeneralUtility::trimExplode('->', $switchableControllerActionPartFromFlexForm);
if (empty($controller) || empty($action)) {
throw new \TYPO3\CMS\Extbase\Configuration\Exception\ParseErrorException('Controller or action were empty when overriding switchableControllerActions from flexForm.', 1257146403);
}
$newSwitchableControllerActionsFromFlexForm[$controller][] = $action;
}
if (!empty($newSwitchableControllerActionsFromFlexForm)) {
$this->overrideSwitchableControllerActions($frameworkConfiguration, $newSwitchableControllerActionsFromFlexForm);
}
return $frameworkConfiguration;
}
/**
* Returns a comma separated list of storagePid that are below a certain storage pid.
*
* @param string $storagePid Storage PID to start at; multiple PIDs possible as comma-separated list
* @param int $recursionDepth Maximum number of levels to search, 0 to disable recursive lookup
* @return string storage PIDs
*/
protected function getRecursiveStoragePids($storagePid, $recursionDepth = 0)
{
if ($recursionDepth <= 0) {
return $storagePid;
}
$recursiveStoragePids = '';
$storagePids = GeneralUtility::intExplode(',', $storagePid);
foreach ($storagePids as $startPid) {
$pids = $this->getContentObject()->getTreeList($startPid, $recursionDepth, 0);
if ((string)$pids !== '') {
$recursiveStoragePids .= $pids . ',';
}
}
return rtrim($recursiveStoragePids, ',');
}
}