From e4105acedf6265f5979dee13d428eeb8667290d7 Mon Sep 17 00:00:00 2001 From: Nikita Hovratov <nikita.h@live.de> Date: Sat, 9 Dec 2023 21:55:25 +0100 Subject: [PATCH] [TASK] Extract registration of controller actions into separate method EU::configurePlugin tightly couples registration of controller actions and TypoScript generation for a frontend rendering definition. Furthermore, lib.contentElement is only defined in fluid_styled_content, which makes it an indirect requirement. This patch extracts the part for the controller action registration, so it can be used independently of fluid_styled_content. In addition, this new method expects the controller actions to have an array shape already. A converter method ensures compatibility for both string and array syntax. A concrete use-case for internal usage would be Content Blocks, as it would be possible to separately define a Content Block of type "Plugin" and in addition register controller actions for it. Resolves: #102643 Releases: main, 12.4 Change-Id: I74d84f54bdd399934b57b3e49e2209f62b5fda68 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/82181 Reviewed-by: Oliver Bartsch <bo@cedev.de> Tested-by: Oliver Bartsch <bo@cedev.de> Tested-by: core-ci <typo3@b13.com> --- .../Classes/Utility/ExtensionUtility.php | 61 ++++++++++++++----- .../Unit/Utility/ExtensionUtilityTest.php | 39 ++++++++++++ 2 files changed, 84 insertions(+), 16 deletions(-) diff --git a/typo3/sysext/extbase/Classes/Utility/ExtensionUtility.php b/typo3/sysext/extbase/Classes/Utility/ExtensionUtility.php index 9fc7beabd11b..aba43e713d57 100644 --- a/typo3/sysext/extbase/Classes/Utility/ExtensionUtility.php +++ b/typo3/sysext/extbase/Classes/Utility/ExtensionUtility.php @@ -52,23 +52,10 @@ class ExtensionUtility $extensionName = str_replace(' ', '', ucwords(str_replace('_', ' ', $extensionName))); $pluginSignature = strtolower($extensionName . '_' . $pluginName); - if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName] ?? false)) { - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName] = []; - } - foreach ($controllerActions as $controllerClassName => $actionsList) { - $controllerAlias = self::resolveControllerAliasFromControllerClassName($controllerClassName); - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerClassName] = [ - 'className' => $controllerClassName, - 'alias' => $controllerAlias, - 'actions' => GeneralUtility::trimExplode(',', (string)$actionsList), - ]; - - if (!empty($nonCacheableControllerActions[$controllerClassName])) { - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerClassName]['nonCacheableActions'] - = GeneralUtility::trimExplode(',', (string)$nonCacheableControllerActions[$controllerClassName]); - } - } + $controllerActions = self::actionCommaListToArray($controllerActions); + $nonCacheableControllerActions = self::actionCommaListToArray($nonCacheableControllerActions); + self::registerControllerActions($extensionName, $pluginName, $controllerActions, $nonCacheableControllerActions); switch ($pluginType) { case self::PLUGIN_TYPE_PLUGIN: @@ -100,6 +87,32 @@ tt_content.' . $pluginSignature . ' { ' . $pluginContent, 'defaultContentRendering'); } + /** + * @param array<string, string[]> $controllerActions + * @param array<string, string[]> $nonCacheableControllerActions + * @internal + */ + public static function registerControllerActions(string $extensionName, string $pluginName, array $controllerActions, array $nonCacheableControllerActions): void + { + if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName] ?? false)) { + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName] = []; + } + foreach ($controllerActions as $controllerClassName => $actionsList) { + $controllerAlias = self::resolveControllerAliasFromControllerClassName($controllerClassName); + + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerClassName] = [ + 'className' => $controllerClassName, + 'alias' => $controllerAlias, + 'actions' => $actionsList, + ]; + + if (!empty($nonCacheableControllerActions[$controllerClassName])) { + $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerClassName]['nonCacheableActions'] + = $nonCacheableControllerActions[$controllerClassName]; + } + } + } + /** * Register an Extbase PlugIn into backend's list of plugins * FOR USE IN Configuration/TCA/Overrides/tt_content.php @@ -199,6 +212,22 @@ tt_content.' . $pluginSignature . ' { ); } + /** + * @param array<string, string|string[]> $controllerActions + * @return array<string, string[]> + */ + protected static function actionCommaListToArray(array $controllerActions): array + { + foreach ($controllerActions as $controllerClassName => $actionsList) { + if (is_array($actionsList)) { + continue; + } + $actionsListArray = GeneralUtility::trimExplode(',', (string)$actionsList); + $controllerActions[$controllerClassName] = $actionsListArray; + } + return $controllerActions; + } + /** * Register a type converter by class name. * diff --git a/typo3/sysext/extbase/Tests/Unit/Utility/ExtensionUtilityTest.php b/typo3/sysext/extbase/Tests/Unit/Utility/ExtensionUtilityTest.php index 6115f3d9fb23..0eda20b5b74f 100644 --- a/typo3/sysext/extbase/Tests/Unit/Utility/ExtensionUtilityTest.php +++ b/typo3/sysext/extbase/Tests/Unit/Utility/ExtensionUtilityTest.php @@ -202,6 +202,45 @@ final class ExtensionUtilityTest extends UnitTestCase self::assertEquals($expectedResult, $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions']['MyExtension']['plugins']['Pi1']); } + /** + * @test + */ + public function configurePluginWorksForMultipleControllerActionsAsArrayWithCacheableActionAsDefault(): void + { + $GLOBALS['TYPO3_CONF_VARS']['FE']['defaultTypoScript_setup.'] = []; + ExtensionUtility::configurePlugin('MyExtension', 'Pi1', [ + FirstController::class => ['index', 'show', 'new', 'create', 'delete', 'edit', 'update'], + SecondController::class => ['index', 'show', 'delete'], + ThirdController::class => ['create'], + ], [ + FirstController::class => ['new', 'create', 'edit', 'update'], + ThirdController::class => ['create'], + ]); + $expectedResult = [ + 'controllers' => [ + FirstController::class => [ + 'className' => FirstController::class, + 'alias' => 'First', + 'actions' => ['index', 'show', 'new', 'create', 'delete', 'edit', 'update'], + 'nonCacheableActions' => ['new', 'create', 'edit', 'update'], + ], + SecondController::class => [ + 'className' => SecondController::class, + 'alias' => 'Second', + 'actions' => ['index', 'show', 'delete'], + ], + ThirdController::class => [ + 'className' => ThirdController::class, + 'alias' => 'Third', + 'actions' => ['create'], + 'nonCacheableActions' => ['create'], + ], + ], + 'pluginType' => 'list_type', + ]; + self::assertEquals($expectedResult, $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions']['MyExtension']['plugins']['Pi1']); + } + /** * @test */ -- GitLab