[FEATURE] Skip default controller and action in generated URIs
authorBastian Waidelich <bastian@typo3.org>
Thu, 1 Sep 2011 16:35:41 +0000 (18:35 +0200)
committerBastian Waidelich <bastian@typo3.org>
Tue, 13 Sep 2011 18:45:23 +0000 (20:45 +0200)
This adds a new feature that leaves out controller and/or action
arguments from generated URIs if they are equal to the default
controller/action of the target plugin.
NOTE: This feature is disabled by default because it has
unpredictable side-effects, if you override default action/controllers
via Flexform.
You can enable this with following TypoScript:
plugin.tx_<yourExtensionName>.features.skipDefaultArguments = 1

But make sure that you're not using "switchableControllerActions"
settings in your plugin FlexForms for this extension.

Change-Id: I5baf0b3f3e5470bf8eec5537af7bd5246caa1c24
Resolves: #8344

typo3/sysext/extbase/Classes/MVC/Web/Routing/UriBuilder.php
typo3/sysext/extbase/Classes/Service/ExtensionService.php
typo3/sysext/extbase/Tests/Unit/MVC/Web/Routing/UriBuilderTest.php
typo3/sysext/extbase/Tests/Unit/Service/ExtensionServiceTest.php
typo3/sysext/extbase/ext_typoscript_setup.txt

index 98cf4a5..d9cb9f5 100644 (file)
@@ -489,6 +489,9 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
                if ($pluginName === NULL) {
                        $pluginName = $this->request->getPluginName();
                }
+               if (TYPO3_MODE === 'FE' && $this->configurationManager->isFeatureEnabled('skipDefaultArguments')) {
+                       $controllerArguments = $this->removeDefaultControllerAndAction($controllerArguments, $extensionName, $pluginName);
+               }
                if ($this->targetPageUid === NULL && TYPO3_MODE === 'FE') {
                        $this->targetPageUid = $this->extensionService->getTargetPidByPlugin($extensionName, $pluginName);
                }
@@ -507,6 +510,31 @@ class Tx_Extbase_MVC_Web_Routing_UriBuilder {
        }
 
        /**
+        * This removes controller and/or action arguments from given controllerArguments
+        * if they are equal to the default controller/action of the target plugin.
+        * Note: This is only active in FE mode and if feature "skipDefaultArguments" is enabled
+        * @see Tx_Extbase_Configuration_ConfigurationManagerInterface::isFeatureEnabled()
+        *
+        * @param array $controllerArguments the current controller arguments to be modified
+        * @param string $extensionName target extension name
+        * @param string $pluginName target plugin name
+        * @return array
+        */
+       protected function removeDefaultControllerAndAction(array $controllerArguments, $extensionName, $pluginName) {
+               $defaultControllerName = $this->extensionService->getDefaultControllerNameByPlugin($extensionName, $pluginName);
+               if (isset($controllerArguments['action'])) {
+                       $defaultActionName = $this->extensionService->getDefaultActionNameByPluginAndController($extensionName, $pluginName, $controllerArguments['controller']);
+                       if ($controllerArguments['action'] === $defaultActionName) {
+                               unset($controllerArguments['action']);
+                       }
+               }
+               if ($controllerArguments['controller'] === $defaultControllerName) {
+                       unset($controllerArguments['controller']);
+               }
+               return $controllerArguments;
+       }
+
+       /**
         * Builds the URI
         * Depending on the current context this calls buildBackendUri() or buildFrontendUri()
         *
index 49493e5..a011f05 100644 (file)
@@ -177,5 +177,36 @@ class Tx_Extbase_Service_ExtensionService implements t3lib_Singleton {
                return (integer)$frameworkConfiguration['view']['defaultPid'];
        }
 
+       /**
+        * This returns the name of the first controller of the given plugin.
+        *
+        * @param string $extensionName name of the extension to retrieve the target PID for
+        * @param string $pluginName name of the plugin to retrieve the target PID for
+        * @return string
+        */
+       public function getDefaultControllerNameByPlugin($extensionName, $pluginName) {
+               if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'])) {
+                       return;
+               }
+               $controllers = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'];
+               return key($controllers);
+       }
+
+       /**
+        * This returns the name of the first action of the given plugin controller.
+        *
+        * @param string $extensionName name of the extension to retrieve the target PID for
+        * @param string $pluginName name of the plugin to retrieve the target PID for
+        * @param string $controllerName name of the controller to retrieve default action for
+        * @return string
+        */
+       public function getDefaultActionNameByPluginAndController($extensionName, $pluginName, $controllerName) {
+               if (!is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerName]['actions'])) {
+                       return;
+               }
+               $actions = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['plugins'][$pluginName]['controllers'][$controllerName]['actions'];
+               return current($actions);
+       }
+
 }
 ?>
\ No newline at end of file
index b1b936a..732fb3b 100644 (file)
@@ -40,6 +40,11 @@ class Tx_Extbase_Tests_Unit_MVC_Web_Routing_UriBuilderTest extends Tx_Extbase_Te
        protected $getBackup;
 
        /**
+        * @var Tx_Extbase_Configuration_ConfigurationManagerInterface
+        */
+       protected $mockConfigurationManager;
+
+       /**
         * @var tslib_cObj
         */
        protected $mockContentObject;
@@ -68,10 +73,12 @@ class Tx_Extbase_Tests_Unit_MVC_Web_Routing_UriBuilderTest extends Tx_Extbase_Te
                $this->mockContentObject = $this->getMock('tslib_cObj');
                $this->mockRequest = $this->getMock('Tx_Extbase_MVC_Web_Request');
                $this->mockExtensionService = $this->getMock('Tx_Extbase_Service_ExtensionService');
+               $this->mockConfigurationManager = $this->getMock('Tx_Extbase_Configuration_ConfigurationManagerInterface');
 
                $this->uriBuilder = $this->getAccessibleMock('Tx_Extbase_MVC_Web_Routing_UriBuilder', array('build'));
                $this->uriBuilder->setRequest($this->mockRequest);
                $this->uriBuilder->_set('contentObject', $this->mockContentObject);
+               $this->uriBuilder->injectConfigurationManager($this->mockConfigurationManager);
 
                $this->uriBuilder->injectExtensionService($this->mockExtensionService);
        }
@@ -641,6 +648,69 @@ class Tx_Extbase_Tests_Unit_MVC_Web_Routing_UriBuilderTest extends Tx_Extbase_Te
                $this->assertEquals($expectedResult, $actualResult);
        }
 
+       /**
+        * @test
+        */
+       public function removeDefaultControllerAndActionDoesNotModifyArgumentsifSpecifiedControlerAndActionIsNotEqualToDefaults() {
+               $this->mockExtensionService->expects($this->atLeastOnce())->method('getDefaultControllerNameByPlugin')->with('ExtensionName', 'PluginName')->will($this->returnValue('DefaultController'));
+               $this->mockExtensionService->expects($this->atLeastOnce())->method('getDefaultActionNameByPluginAndController')->with('ExtensionName', 'PluginName', 'SomeController')->will($this->returnValue('defaultAction'));
+
+               $arguments = array('controller' => 'SomeController', 'action' => 'someAction', 'foo' => 'bar');
+               $extensionName = 'ExtensionName';
+               $pluginName = 'PluginName';
+               $expectedResult = array('controller' => 'SomeController', 'action' => 'someAction', 'foo' => 'bar');
+
+               $actualResult = $this->uriBuilder->_callRef('removeDefaultControllerAndAction', $arguments, $extensionName, $pluginName);
+               $this->assertEquals($expectedResult, $actualResult);
+       }
+
+       /**
+        * @test
+        */
+       public function removeDefaultControllerAndActionRemovesControllerIfItIsEqualToTheDefault() {
+               $this->mockExtensionService->expects($this->atLeastOnce())->method('getDefaultControllerNameByPlugin')->with('ExtensionName', 'PluginName')->will($this->returnValue('DefaultController'));
+               $this->mockExtensionService->expects($this->atLeastOnce())->method('getDefaultActionNameByPluginAndController')->with('ExtensionName', 'PluginName', 'DefaultController')->will($this->returnValue('defaultAction'));
+
+               $arguments = array('controller' => 'DefaultController', 'action' => 'someAction', 'foo' => 'bar');
+               $extensionName = 'ExtensionName';
+               $pluginName = 'PluginName';
+               $expectedResult = array('action' => 'someAction', 'foo' => 'bar');
+
+               $actualResult = $this->uriBuilder->_callRef('removeDefaultControllerAndAction', $arguments, $extensionName, $pluginName);
+               $this->assertEquals($expectedResult, $actualResult);
+       }
+
+       /**
+        * @test
+        */
+       public function removeDefaultControllerAndActionRemovesActionIfItIsEqualToTheDefault() {
+               $this->mockExtensionService->expects($this->atLeastOnce())->method('getDefaultControllerNameByPlugin')->with('ExtensionName', 'PluginName')->will($this->returnValue('DefaultController'));
+               $this->mockExtensionService->expects($this->atLeastOnce())->method('getDefaultActionNameByPluginAndController')->with('ExtensionName', 'PluginName', 'SomeController')->will($this->returnValue('defaultAction'));
+
+               $arguments = array('controller' => 'SomeController', 'action' => 'defaultAction', 'foo' => 'bar');
+               $extensionName = 'ExtensionName';
+               $pluginName = 'PluginName';
+               $expectedResult = array('controller' => 'SomeController', 'foo' => 'bar');
+
+               $actualResult = $this->uriBuilder->_callRef('removeDefaultControllerAndAction', $arguments, $extensionName, $pluginName);
+               $this->assertEquals($expectedResult, $actualResult);
+       }
+
+       /**
+        * @test
+        */
+       public function removeDefaultControllerAndActionRemovesControllerAndActionIfBothAreEqualToTheDefault() {
+               $this->mockExtensionService->expects($this->atLeastOnce())->method('getDefaultControllerNameByPlugin')->with('ExtensionName', 'PluginName')->will($this->returnValue('DefaultController'));
+               $this->mockExtensionService->expects($this->atLeastOnce())->method('getDefaultActionNameByPluginAndController')->with('ExtensionName', 'PluginName', 'DefaultController')->will($this->returnValue('defaultAction'));
+
+               $arguments = array('controller' => 'DefaultController', 'action' => 'defaultAction', 'foo' => 'bar');
+               $extensionName = 'ExtensionName';
+               $pluginName = 'PluginName';
+               $expectedResult = array('foo' => 'bar');
+
+               $actualResult = $this->uriBuilder->_callRef('removeDefaultControllerAndAction', $arguments, $extensionName, $pluginName);
+               $this->assertEquals($expectedResult, $actualResult);
+       }
 
 }
 ?>
\ No newline at end of file
index 52b53c1..4ba1cf9 100644 (file)
@@ -296,5 +296,58 @@ class Tx_Extbase_Tests_Unit_Service_ExtensionServiceTest extends Tx_Extbase_Test
                $this->extensionService->getTargetPidByPlugin('ExtensionName', 'SomePlugin');
        }
 
+       /**
+        * @test
+        */
+       public function getDefaultControllerNameByPluginReturnsNullIfGivenExtensionCantBeFound() {
+               $this->assertNull($this->extensionService->getDefaultControllerNameByPlugin('NonExistingExtensionName', 'SomePlugin'));
+       }
+
+       /**
+        * @test
+        */
+       public function getDefaultControllerNameByPluginReturnsNullIfGivenPluginCantBeFound() {
+               $this->assertNull($this->extensionService->getDefaultControllerNameByPlugin('ExtensionName', 'NonExistingPlugin'));
+       }
+
+       /**
+        * @test
+        */
+       public function getDefaultControllerNameByPluginReturnsFirstControllerNameOfGivenPlugin() {
+               $expectedResult = 'ControllerName';
+               $actualResult = $this->extensionService->getDefaultControllerNameByPlugin('ExtensionName', 'SomePlugin');
+               $this->assertEquals($expectedResult, $actualResult);
+       }
+
+       /**
+        * @test
+        */
+       public function getDefaultActionNameByPluginAndControllerReturnsNullIfGivenExtensionCantBeFound() {
+               $this->assertNull($this->extensionService->getDefaultActionNameByPluginAndController('NonExistingExtensionName', 'SomePlugin', 'ControllerName'));
+       }
+
+       /**
+        * @test
+        */
+       public function getDefaultActionNameByPluginAndControllerReturnsNullIfGivenPluginCantBeFound() {
+               $this->assertNull($this->extensionService->getDefaultActionNameByPluginAndController('ExtensionName', 'NonExistingPlugin', 'ControllerName'));
+       }
+
+       /**
+        * @test
+        */
+       public function getDefaultActionNameByPluginAndControllerReturnsNullIfGivenControllerCantBeFound() {
+               $this->assertNull($this->extensionService->getDefaultActionNameByPluginAndController('ExtensionName', 'SomePlugin', 'NonExistingControllerName'));
+       }
+
+       /**
+        * @test
+        */
+       public function getDefaultActionNameByPluginAndControllerReturnsFirstActionNameOfGivenController() {
+               $expectedResult = 'someAction';
+               $actualResult = $this->extensionService->getDefaultActionNameByPluginAndController('SomeOtherExtensionName', 'SecondPlugin', 'SecondControllerName');
+               $this->assertEquals($expectedResult, $actualResult);
+       }
+
 }
 ?>
\ No newline at end of file
index 6853d81..24e583d 100644 (file)
@@ -37,5 +37,8 @@ config.tx_extbase {
                        }
                }
        }
-       features.rewrittenPropertyMapper = 1
+       features {
+               rewrittenPropertyMapper = 1
+               skipDefaultArguments = 0
+       }
 }
\ No newline at end of file