[BUGFIX] Default action is not properly resolved
authorBastian Waidelich <bastian@typo3.org>
Thu, 15 Sep 2011 17:11:10 +0000 (19:11 +0200)
committerBastian Waidelich <bastian@typo3.org>
Thu, 15 Sep 2011 17:11:10 +0000 (19:11 +0200)
When no action is specified, Extbase returns the first action
name of the default controller.
If another controller name is specified though (and no action name),
Extbase still returned the first action name of the default
controller. Instead it should obviously return the first action
name of the given controller in that case.

This is fixed by this change.

Besides invalid controller names now also trigger an exception

Change-Id: Ib4d5bbc078084206a9cdd13b0cae09926f463669
Resolves: #29875

typo3/sysext/extbase/Classes/MVC/Web/RequestBuilder.php
typo3/sysext/extbase/Tests/Unit/MVC/Web/RequestBuilderTest.php

index 2af2650..3d8af4b 100644 (file)
@@ -63,13 +63,6 @@ class Tx_Extbase_MVC_Web_RequestBuilder implements t3lib_Singleton {
        protected $defaultControllerName;
 
        /**
-        * The default action of the default controller
-        *
-        * @var string
-        */
-       protected $defaultActionName;
-
-       /**
         * The default format of the response object
         *
         * @var string
@@ -132,13 +125,11 @@ class Tx_Extbase_MVC_Web_RequestBuilder implements t3lib_Singleton {
                $this->extensionName = $configuration['extensionName'];
                $this->pluginName = $configuration['pluginName'];
                $this->defaultControllerName = current(array_keys($configuration['controllerConfiguration']));
-               $this->defaultActionName = current($configuration['controllerConfiguration'][$this->defaultControllerName]['actions']);
 
-               $allowedControllerActions = array();
+               $this->allowedControllerActions = array();
                foreach ($configuration['controllerConfiguration'] as $controllerName => $controllerActions) {
-                       $allowedControllerActions[$controllerName] = $controllerActions['actions'];
+                       $this->allowedControllerActions[$controllerName] = $controllerActions['actions'];
                }
-               $this->allowedControllerActions = $allowedControllerActions;
                if (!empty($configuration['format'])) {
                        $this->defaultFormat = $configuration['format'];
                }
@@ -189,16 +180,30 @@ class Tx_Extbase_MVC_Web_RequestBuilder implements t3lib_Singleton {
         * @throws Tx_Extbase_MVC_Exception if the controller could not be resolved
         */
        protected function resolveControllerName(array $parameters) {
-               if (isset($parameters['controller']) && in_array($parameters['controller'], $this->allowedControllerActions)) {
-                       return filter_var($parameters['controller'], FILTER_SANITIZE_STRING);
-               } elseif (!empty($this->defaultControllerName)) {
+               if (!isset($parameters['controller']) || strlen($parameters['controller']) === 0) {
+                       if (strlen($this->defaultControllerName) === 0) {
+                               throw new Tx_Extbase_MVC_Exception(
+                                       'The default controller can not be determined. Please check for Tx_Extbase_Utility_Extension::configurePlugin() in your ext_localconf.php.',
+                                       1316104317
+                               );
+                       }
                        return $this->defaultControllerName;
-               } else {
-                       throw new Tx_Extbase_MVC_Exception(
-                               'The default controller can not be determined. Please check for Tx_Extbase_Utility_Extension::configurePlugin() in your ext_localconf.php.',
-                               1295479650
+               }
+               $allowedControllerNames = array_keys($this->allowedControllerActions);
+               if (!in_array($parameters['controller'], $allowedControllerNames)) {
+                       $configuration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
+                       if (isset($configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) && (boolean)$configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) {
+                               throw new t3lib_error_http_PageNotFoundException(
+                                       'The requested resource was not found',
+                                       1313857897
+                               );
+                       }
+                       throw new Tx_Extbase_MVC_Exception_InvalidControllerName(
+                               'The controller "' . $parameters['controller'] . '" is not allowed by this plugin. Please check for Tx_Extbase_Utility_Extension::configurePlugin() in your ext_localconf.php.',
+                               1313855173
                        );
                }
+               return filter_var($parameters['controller'], FILTER_SANITIZE_STRING);
        }
 
        /**
@@ -213,17 +218,18 @@ class Tx_Extbase_MVC_Web_RequestBuilder implements t3lib_Singleton {
         */
        protected function resolveActionName($controllerName, array $parameters) {
                if (!isset($parameters['action']) || strlen($parameters['action']) === 0) {
-                       if (!empty($this->defaultActionName)) {
-                               return $this->defaultActionName;
+                       $defaultActionName = is_array($this->allowedControllerActions[$controllerName]) ? current($this->allowedControllerActions[$controllerName]) : '';
+                       if (strlen($defaultActionName) === 0) {
+                               throw new Tx_Extbase_MVC_Exception(
+                                       'The default action can not be determined for controller "' . $controllerName . '". Please check Tx_Extbase_Utility_Extension::configurePlugin() in your ext_localconf.php.',
+                                       1295479651
+                               );
                        }
-                       throw new Tx_Extbase_MVC_Exception(
-                               'The default action can not be determined for controller "' . $controllerName . '". Please check Tx_Extbase_Utility_Extension::configurePlugin() in your ext_localconf.php.',
-                               1295479651
-                       );
+                       return $defaultActionName;
                }
                $actionName = $parameters['action'];
-               $allowedActions = $this->allowedControllerActions[$controllerName];
-               if (!in_array($actionName, $allowedActions)) {
+               $allowedActionNames = $this->allowedControllerActions[$controllerName];
+               if (!in_array($actionName, $allowedActionNames)) {
                        $configuration = $this->configurationManager->getConfiguration(Tx_Extbase_Configuration_ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
                        if (isset($configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) && (boolean)$configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved']) {
                                throw new t3lib_error_http_PageNotFoundException(
@@ -232,7 +238,7 @@ class Tx_Extbase_MVC_Web_RequestBuilder implements t3lib_Singleton {
                                );
                        }
                        throw new Tx_Extbase_MVC_Exception_InvalidActionName(
-                               'There is no action "' . $actionName . '" for controller "' . $controllerName . '".',
+                               'The action "' . $actionName . '" (controller "' . $controllerName . '") is not allowed by this plugin. Please check Tx_Extbase_Utility_Extension::configurePlugin() in your ext_localconf.php.',
                                1313855173
                        );
                }
index 332b5e0..a13fc9f 100644 (file)
@@ -88,7 +88,7 @@ class Tx_Extbase_Tests_Unit_MVC_Web_RequestBuilderTest extends Tx_Extbase_Tests_
                                        'actions' => array('show', 'index')
                                ),
                                'TheThirdController' => array(
-                                       'actions' => array('delete', 'create')
+                                       'actions' => array('delete', 'create', 'onlyInThirdController')
                                )
                        )
                );
@@ -251,30 +251,6 @@ class Tx_Extbase_Tests_Unit_MVC_Web_RequestBuilderTest extends Tx_Extbase_Tests_
 
        /**
         * @test
-        * @expectedException Tx_Extbase_MVC_Exception_InvalidActionName
-        */
-       public function resolveActionNameThrowsInvalidActionExceptionIfSpecifiedActionIsNotAllowed() {
-               $this->requestBuilder->injectConfigurationManager($this->mockConfigurationManager);
-               $this->requestBuilder->injectExtensionService($this->mockExtensionService);
-               $parameters = array('action' => 'new');
-               $this->requestBuilder->_call('resolveActionName', 'TheSecondController', $parameters);
-       }
-
-       /**
-        * @test
-        * @expectedException t3lib_error_http_PageNotFoundException
-        */
-       public function resolveActionNameThrowsPageNotFoundExceptionIfSpecifiedActionIsNotAllowedAndPageNotFoundExceptionIsConfigured() {
-               $this->configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved'] = 1;
-               $this->mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($this->configuration));
-               $this->requestBuilder->injectConfigurationManager($this->mockConfigurationManager);
-               $this->requestBuilder->injectExtensionService($this->mockExtensionService);
-               $parameters = array('action' => 'new');
-               $this->requestBuilder->_call('resolveActionName', 'TheSecondController', $parameters);
-       }
-
-       /**
-        * @test
         * @expectedException Tx_Extbase_MVC_Exception
         */
        public function buildThrowsExceptionIfNoDefaultControllerCanBeResolved() {
@@ -361,7 +337,7 @@ class Tx_Extbase_Tests_Unit_MVC_Web_RequestBuilderTest extends Tx_Extbase_Tests_
                                'show', 'index'
                        ),
                        'TheThirdController' => array(
-                               'delete', 'create'
+                               'delete', 'create', 'onlyInThirdController'
                        )
                );
                $this->requestBuilder->build();
@@ -369,5 +345,187 @@ class Tx_Extbase_Tests_Unit_MVC_Web_RequestBuilderTest extends Tx_Extbase_Tests_
                $this->assertEquals($expectedResult, $actualResult);
        }
 
+       /**
+        * @test
+        * @expectedException Tx_Extbase_MVC_Exception
+        */
+       public function buildThrowsExceptionIfDefaultControllerCantBeDetermined() {
+               $this->configuration['controllerConfiguration'] = array();
+
+               $this->mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($this->configuration));
+               $this->requestBuilder->injectConfigurationManager($this->mockConfigurationManager);
+
+               $this->mockExtensionService->expects($this->any())->method('getPluginNamespace')->will($this->returnValue('tx_myextension_pi1'));
+               $this->requestBuilder->injectExtensionService($this->mockExtensionService);
+
+               $this->requestBuilder->build();
+       }
+
+       /**
+        * @test
+        */
+       public function buildSetsDefaultControllerIfNoControllerIsSpecified() {
+               $this->injectDependencies();
+               $_GET = array(
+                       'tx_myextension_pi1' => array(
+                               'foo' => 'bar',
+                       )
+               );
+               $this->mockRequest->expects($this->once())->method('setControllerName')->with('TheFirstController');
+               $this->requestBuilder->build();
+       }
+
+       /**
+        * @test
+        */
+       public function buildCorrectlySetsSpecifiedControllerNameIfItsAllowedForTheCurrentPlugin() {
+               $this->injectDependencies();
+               $_GET = array(
+                       'tx_myextension_pi1' => array(
+                               'controller' => 'TheSecondController',
+                       )
+               );
+               $this->mockRequest->expects($this->once())->method('setControllerName')->with('TheSecondController');
+               $this->requestBuilder->build();
+       }
+
+       /**
+        * @test
+        * @expectedException Tx_Extbase_MVC_Exception_InvalidControllerName
+        */
+       public function buildThrowsInvalidControllerNameExceptionIfSpecifiedControllerIsNotAllowed() {
+               $this->mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($this->configuration));
+               $this->requestBuilder->injectConfigurationManager($this->mockConfigurationManager);
+
+               $this->mockExtensionService->expects($this->any())->method('getPluginNamespace')->will($this->returnValue('tx_myextension_pi1'));
+               $this->requestBuilder->injectExtensionService($this->mockExtensionService);
+
+               $_GET = array(
+                       'tx_myextension_pi1' => array(
+                               'controller' => 'SomeIllegalController',
+                       )
+               );
+               $this->requestBuilder->build();
+       }
+
+       /**
+        * @test
+        * @expectedException t3lib_error_http_PageNotFoundException
+        */
+       public function buildThrowsPageNotFoundExceptionIfEnabledAndSpecifiedControllerIsNotAllowed() {
+               $this->configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved'] = 1;
+               $this->mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($this->configuration));
+               $this->requestBuilder->injectConfigurationManager($this->mockConfigurationManager);
+
+               $this->mockExtensionService->expects($this->any())->method('getPluginNamespace')->will($this->returnValue('tx_myextension_pi1'));
+               $this->requestBuilder->injectExtensionService($this->mockExtensionService);
+
+               $_GET = array(
+                       'tx_myextension_pi1' => array(
+                               'controller' => 'SomeIllegalController',
+                       )
+               );
+               $this->requestBuilder->build();
+       }
+
+
+       /**
+        * @test
+        * @expectedException Tx_Extbase_MVC_Exception
+        */
+       public function buildThrowsExceptionIfDefaultActionCantBeDetermined() {
+               $this->configuration['controllerConfiguration'] = array();
+
+               $this->mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($this->configuration));
+               $this->requestBuilder->injectConfigurationManager($this->mockConfigurationManager);
+
+               $this->mockExtensionService->expects($this->any())->method('getPluginNamespace')->will($this->returnValue('tx_myextension_pi1'));
+               $this->requestBuilder->injectExtensionService($this->mockExtensionService);
+
+               $this->requestBuilder->build();
+       }
+
+       /**
+        * @test
+        */
+       public function buildSetsDefaultActionOfTheCurrentControllerIfNoActionIsSpecified() {
+               $this->injectDependencies();
+               $_GET = array(
+                       'tx_myextension_pi1' => array(
+                               'controller' => 'TheThirdController',
+                       )
+               );
+               $this->mockRequest->expects($this->once())->method('setControllerActionName')->with('delete');
+               $this->requestBuilder->build();
+       }
+
+       /**
+        * @test
+        */
+       public function buildCorrectlySetsSpecifiedActionNameForTheDefaultControllerIfItsAllowedForTheCurrentPlugin() {
+               $this->injectDependencies();
+               $_GET = array(
+                       'tx_myextension_pi1' => array(
+                               'action' => 'create',
+                       )
+               );
+               $this->mockRequest->expects($this->once())->method('setControllerActionName')->with('create');
+               $this->requestBuilder->build();
+       }
+
+       /**
+        * @test
+        */
+       public function buildCorrectlySetsSpecifiedActionNameForTheSpecifiedControllerIfItsAllowedForTheCurrentPlugin() {
+               $this->injectDependencies();
+               $_GET = array(
+                       'tx_myextension_pi1' => array(
+                               'controller' => 'TheThirdController',
+                               'action' => 'onlyInThirdController',
+                       )
+               );
+               $this->mockRequest->expects($this->once())->method('setControllerActionName')->with('onlyInThirdController');
+               $this->requestBuilder->build();
+       }
+
+       /**
+        * @test
+        * @expectedException Tx_Extbase_MVC_Exception_InvalidActionName
+        */
+       public function buildThrowsInvalidActionNameExceptionIfSpecifiedActionIsNotAllowed() {
+               $this->mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($this->configuration));
+               $this->requestBuilder->injectConfigurationManager($this->mockConfigurationManager);
+
+               $this->mockExtensionService->expects($this->any())->method('getPluginNamespace')->will($this->returnValue('tx_myextension_pi1'));
+               $this->requestBuilder->injectExtensionService($this->mockExtensionService);
+
+               $_GET = array(
+                       'tx_myextension_pi1' => array(
+                               'action' => 'someIllegalAction',
+                       )
+               );
+               $this->requestBuilder->build();
+       }
+
+       /**
+        * @test
+        * @expectedException t3lib_error_http_PageNotFoundException
+        */
+       public function buildThrowsPageNotFoundExceptionIfEnabledAndSpecifiedActionIsNotAllowed() {
+               $this->configuration['mvc']['throwPageNotFoundExceptionIfActionCantBeResolved'] = 1;
+               $this->mockConfigurationManager->expects($this->any())->method('getConfiguration')->will($this->returnValue($this->configuration));
+               $this->requestBuilder->injectConfigurationManager($this->mockConfigurationManager);
+
+               $this->mockExtensionService->expects($this->any())->method('getPluginNamespace')->will($this->returnValue('tx_myextension_pi1'));
+               $this->requestBuilder->injectExtensionService($this->mockExtensionService);
+
+               $_GET = array(
+                       'tx_myextension_pi1' => array(
+                               'action' => 'someIllegalAction',
+                       )
+               );
+               $this->requestBuilder->build();
+       }
+
 }
 ?>
\ No newline at end of file