‪TYPO3CMS  11.5
AbstractConfigurationManager.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\ServerRequestInterface;
27 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
28 
34 {
39 
45  protected ‪$configuration = [];
46 
50  protected ‪$contentObject;
51 
53 
59  protected ‪$extensionName;
60 
66  protected ‪$pluginName;
67 
73  protected ‪$configurationCache = [];
74 
76  {
77  $this->typoScriptService = ‪$typoScriptService;
78  }
79 
84  public function ‪setContentObject(ContentObjectRenderer ‪$contentObject): void
85  {
86  $this->contentObject = ‪$contentObject;
87  }
88 
98  public function ‪getContentObject(): ?ContentObjectRenderer
99  {
100  if ($this->contentObject instanceof ContentObjectRenderer) {
102  }
103  $this->contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
105  }
106 
113  public function ‪setConfiguration(array ‪$configuration = []): void
114  {
115  // reset 1st level cache
116  $this->configurationCache = [];
117  $this->extensionName = ‪$configuration['extensionName'] ?? null;
118  $this->pluginName = ‪$configuration['pluginName'] ?? null;
119  $this->configuration = $this->typoScriptService->convertTypoScriptArrayToPlainArray(‪$configuration);
120  }
121 
132  public function ‪getConfiguration(?string ‪$extensionName = null, ?string ‪$pluginName = null): array
133  {
134  // 1st level cache
135  $configurationCacheKey = strtolower((‪$extensionName ?: $this->extensionName) . '_' . (‪$pluginName ?: $this->pluginName));
136  if (isset($this->configurationCache[$configurationCacheKey])) {
137  return $this->configurationCache[$configurationCacheKey];
138  }
139  $frameworkConfiguration = $this->‪getExtbaseConfiguration();
140  if (!isset($frameworkConfiguration['persistence']['storagePid'])) {
141  $frameworkConfiguration['persistence']['storagePid'] = $this->‪getDefaultBackendStoragePid();
142  }
143  // only merge $this->configuration and override controller configuration when retrieving configuration of the current plugin
144  if ($extensionName === null || ‪$extensionName === $this->extensionName && ‪$pluginName === $this->pluginName) {
145  $pluginConfiguration = $this->‪getPluginConfiguration((string)$this->extensionName, (string)$this->pluginName);
146  ‪ArrayUtility::mergeRecursiveWithOverrule($pluginConfiguration, $this->configuration);
147  $pluginConfiguration['controllerConfiguration'] = $this->‪getControllerConfiguration((string)$this->extensionName, (string)$this->pluginName);
148  if (isset($this->configuration['switchableControllerActions'])) {
149  $this->‪overrideControllerConfigurationWithSwitchableControllerActions($pluginConfiguration, $this->configuration['switchableControllerActions']);
150  }
151  } else {
152  $pluginConfiguration = $this->‪getPluginConfiguration((string)$extensionName, (string)‪$pluginName);
153  $pluginConfiguration['controllerConfiguration'] = $this->‪getControllerConfiguration((string)$extensionName, (string)‪$pluginName);
154  }
155  ‪ArrayUtility::mergeRecursiveWithOverrule($frameworkConfiguration, $pluginConfiguration);
156  // only load context specific configuration when retrieving configuration of the current plugin
157  if (‪$extensionName === null || ‪$extensionName === $this->extensionName && ‪$pluginName === $this->pluginName) {
158  $frameworkConfiguration = $this->‪getContextSpecificFrameworkConfiguration($frameworkConfiguration);
159  }
160 
161  if (!empty($frameworkConfiguration['persistence']['storagePid'])) {
162  if (is_array($frameworkConfiguration['persistence']['storagePid'])) {
163  // We simulate the frontend to enable the use of cObjects in
164  // stdWrap. We then convert the configuration to normal TypoScript
165  // and apply the stdWrap to the storagePid
166  $isBackend = (‪$GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
167  && ‪ApplicationType::fromRequest(‪$GLOBALS['TYPO3_REQUEST'])->isBackend();
168  if ($isBackend) {
169  // @todo: This BE specific switch should be moved to BackendConfigurationManager to drop the dependency to $GLOBALS['TYPO3_REQUEST'] here.
170  // Use makeInstance here since extbase Bootstrap always setContentObject(null) in Backend, no need to call getContentObject().
171  ‪FrontendSimulatorUtility::simulateFrontendEnvironment(GeneralUtility::makeInstance(ContentObjectRenderer::class));
172  }
173  $conf = $this->typoScriptService->convertPlainArrayToTypoScriptArray($frameworkConfiguration['persistence']);
174  $frameworkConfiguration['persistence']['storagePid'] = ‪$GLOBALS['TSFE']->cObj->stdWrapValue('storagePid', $conf);
175  if ($isBackend) {
177  }
178  }
179 
180  if (!empty($frameworkConfiguration['persistence']['recursive'])) {
181  // All implementations of getTreeList allow to pass the ids negative to include them into the result
182  // otherwise only childpages are returned
183  $storagePids = ‪GeneralUtility::intExplode(',', $frameworkConfiguration['persistence']['storagePid']);
184  array_walk($storagePids, static function (&$storagePid) {
185  if ($storagePid > 0) {
186  $storagePid = -$storagePid;
187  }
188  });
189  $storagePids = $this->‪getRecursiveStoragePids(
190  $storagePids,
191  (int)$frameworkConfiguration['persistence']['recursive']
192  );
193 
194  $frameworkConfiguration['persistence']['storagePid'] = implode(',', $storagePids);
195  }
196  }
197  // 1st level cache
198  $this->configurationCache[$configurationCacheKey] = $frameworkConfiguration;
199  return $frameworkConfiguration;
200  }
201 
207  protected function ‪getExtbaseConfiguration(): array
208  {
209  $setup = $this->‪getTypoScriptSetup();
210  $extbaseConfiguration = [];
211  if (isset($setup['config.']['tx_extbase.'])) {
212  $extbaseConfiguration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($setup['config.']['tx_extbase.']);
213  }
214  return $extbaseConfiguration;
215  }
216 
222  public function ‪getDefaultBackendStoragePid(): int
223  {
225  }
226 
248  protected function ‪overrideControllerConfigurationWithSwitchableControllerActions(array &$frameworkConfiguration, array $switchableControllerActions): void
249  {
250  trigger_error(
251  sprintf(
252  'Plugin "%s" of extension "%s" uses switchable controller actions which has been marked as deprecated as of version TYPO3 10 and will be removed in one of the next major versions of TYPO3, probably version 11.0 or 12.0',
253  $frameworkConfiguration['pluginName'] ?? '',
254  $frameworkConfiguration['extensionName'] ?? ''
255  ),
256  E_USER_DEPRECATED
257  );
258 
259  $controllerAliasToClass = [];
260  foreach ($frameworkConfiguration['controllerConfiguration'] as $controllerClass => $controllerConfiguration) {
261  $controllerAliasToClass[$controllerConfiguration['alias']] = $controllerClass;
262  }
263 
264  $overriddenControllerConfiguration = [];
265  foreach ($switchableControllerActions as $controllerName => $actions) {
266  // Trim leading backslashes if a fully qualified controller class name with leading slashes is used.
267  $controllerName = ltrim($controllerName, '\\');
268 
269  $controllerIsConfigured = false;
270  if (array_key_exists($controllerName, $controllerAliasToClass)) {
271  /*
272  * If $controllerName can be found in the keys of $controllerAliasToClass, $controllerName is a
273  * controller alias and not a FQCN. In this case switchable controller actions have been defined with
274  * controller aliases as such:
275  *
276  * tt_content.list.20.indexedsearch_pi2.switchableControllerActions {
277  * Search {
278  * 0 = search
279  * }
280  * }
281  */
282  $controllerIsConfigured = true;
283  $controllerClassName = $controllerAliasToClass[$controllerName];
284  $controllerAlias = $controllerName;
285  }
286 
287  if (in_array($controllerName, $controllerAliasToClass, true)) {
288  /*
289  * If $controllerName can be found in the values of $controllerAliasToClass, $controllerName is a
290  * FQCN. In this case switchable controller actions have been defined with fully qualified controller
291  * class names as such:
292  *
293  * tt_content.list.20.indexedsearch_pi2.switchableControllerActions {
294  * TYPO3\CMS\IndexedSearch\Controller\SearchController {
295  * 0 = search
296  * }
297  * }
298  */
299  $controllerIsConfigured = true;
300  $controllerClassName = $controllerName;
301  $controllerAlias = $frameworkConfiguration['controllerConfiguration'][$controllerName]['alias'];
302  }
303 
304  if (!$controllerIsConfigured) {
305  continue;
306  }
307 
308  if (!isset($overriddenControllerConfiguration[$controllerClassName])) {
309  $overriddenControllerConfiguration[$controllerClassName] = [
310  'alias' => $controllerAlias,
311  'className' => $controllerClassName,
312  'actions' => [],
313  ];
314  }
315  $overriddenControllerConfiguration[$controllerClassName]['actions'] = array_merge(
316  $overriddenControllerConfiguration[$controllerClassName]['actions'],
317  $actions
318  );
319  $nonCacheableActions = $frameworkConfiguration['controllerConfiguration'][$controllerClassName]['nonCacheableActions'] ?? null;
320  if (!is_array($nonCacheableActions)) {
321  // There are no non-cacheable actions, thus we can directly continue
322  // with the next controller name.
323  continue;
324  }
325  $overriddenNonCacheableActions = array_intersect($nonCacheableActions, $actions);
326  if (!empty($overriddenNonCacheableActions)) {
327  $overriddenControllerConfiguration[$controllerClassName]['nonCacheableActions'] = $overriddenNonCacheableActions;
328  }
329  }
330  $frameworkConfiguration['controllerConfiguration'] = $overriddenControllerConfiguration;
331  }
332 
344  abstract protected function ‪getContextSpecificFrameworkConfiguration(array $frameworkConfiguration): array;
345 
351  abstract public function ‪getTypoScriptSetup(): array;
352 
361  abstract protected function ‪getPluginConfiguration(string ‪$extensionName, string ‪$pluginName = null): array;
362 
374  abstract protected function ‪getControllerConfiguration(string ‪$extensionName, string ‪$pluginName): array;
375 
384  abstract protected function ‪getRecursiveStoragePids(array $storagePids, int $recursionDepth = 0): array;
385 }
‪TYPO3\CMS\Extbase\Utility\FrontendSimulatorUtility
Definition: FrontendSimulatorUtility.php:30
‪TYPO3\CMS\Extbase\Utility\FrontendSimulatorUtility\simulateFrontendEnvironment
‪static simulateFrontendEnvironment(ContentObjectRenderer $cObj=null)
Definition: FrontendSimulatorUtility.php:40
‪TYPO3\CMS\Core\Http\ApplicationType\fromRequest
‪static static fromRequest(ServerRequestInterface $request)
Definition: ApplicationType.php:62
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\$pluginName
‪string $pluginName
Definition: AbstractConfigurationManager.php:62
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\setContentObject
‪setContentObject(ContentObjectRenderer $contentObject)
Definition: AbstractConfigurationManager.php:79
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\getExtbaseConfiguration
‪array getExtbaseConfiguration()
Definition: AbstractConfigurationManager.php:202
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\__construct
‪__construct(TypoScriptService $typoScriptService)
Definition: AbstractConfigurationManager.php:70
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:654
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager
Definition: AbstractConfigurationManager.php:34
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\getTypoScriptSetup
‪array getTypoScriptSetup()
‪TYPO3\CMS\Core\Http\ApplicationType
Definition: ApplicationType.php:52
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\$typoScriptService
‪TypoScriptService $typoScriptService
Definition: AbstractConfigurationManager.php:50
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\getConfiguration
‪array getConfiguration(?string $extensionName=null, ?string $pluginName=null)
Definition: AbstractConfigurationManager.php:127
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\getContextSpecificFrameworkConfiguration
‪array getContextSpecificFrameworkConfiguration(array $frameworkConfiguration)
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\$configuration
‪array $configuration
Definition: AbstractConfigurationManager.php:44
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\getControllerConfiguration
‪array getControllerConfiguration(string $extensionName, string $pluginName)
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\getRecursiveStoragePids
‪array int[] getRecursiveStoragePids(array $storagePids, int $recursionDepth=0)
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\$contentObject
‪ContentObjectRenderer $contentObject
Definition: AbstractConfigurationManager.php:48
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\$configurationCache
‪array $configurationCache
Definition: AbstractConfigurationManager.php:68
‪TYPO3\CMS\Extbase\Utility\FrontendSimulatorUtility\resetFrontendEnvironment
‪static resetFrontendEnvironment()
Definition: FrontendSimulatorUtility.php:52
‪TYPO3\CMS\Core\TypoScript\TypoScriptService
Definition: TypoScriptService.php:25
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪TYPO3\CMS\Core\SingletonInterface
Definition: SingletonInterface.php:22
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:927
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\getContentObject
‪ContentObjectRenderer getContentObject()
Definition: AbstractConfigurationManager.php:93
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\overrideControllerConfigurationWithSwitchableControllerActions
‪overrideControllerConfigurationWithSwitchableControllerActions(array &$frameworkConfiguration, array $switchableControllerActions)
Definition: AbstractConfigurationManager.php:243
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\getDefaultBackendStoragePid
‪int getDefaultBackendStoragePid()
Definition: AbstractConfigurationManager.php:217
‪TYPO3\CMS\Extbase\Configuration
Definition: AbstractConfigurationManager.php:18
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\getPluginConfiguration
‪array getPluginConfiguration(string $extensionName, string $pluginName=null)
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\$extensionName
‪string $extensionName
Definition: AbstractConfigurationManager.php:56
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\setConfiguration
‪setConfiguration(array $configuration=[])
Definition: AbstractConfigurationManager.php:108
‪TYPO3\CMS\Extbase\Configuration\AbstractConfigurationManager\DEFAULT_BACKEND_STORAGE_PID
‪const DEFAULT_BACKEND_STORAGE_PID
Definition: AbstractConfigurationManager.php:38