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); }