[!!!][TASK] Remove Extbase ModuleRunner 02/42702/5
authorBenjamin Mack <benni@typo3.org>
Mon, 17 Aug 2015 13:00:46 +0000 (15:00 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Tue, 18 Aug 2015 17:08:03 +0000 (19:08 +0200)
The ModuleRunner and its interface were initially designed
to allow backend modules other than the "classic" modules that
need a conf.php and index.php to be a flexible entry point

Resolves: #69148
Releases: master
Change-Id: I695e41544f2154115b95c1b120da7c227abd4bcf
Reviewed-on: http://review.typo3.org/42702
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php
typo3/sysext/backend/Classes/Module/ModuleLoader.php
typo3/sysext/backend/Tests/Unit/Http/BackendModuleRequestHandlerTest.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-69148-BackendModuleDispatchingRemoved.rst [new file with mode: 0644]
typo3/sysext/extbase/Classes/Core/ModuleRunner.php [deleted file]
typo3/sysext/extbase/Classes/Core/ModuleRunnerInterface.php [deleted file]
typo3/sysext/extbase/ext_tables.php

index bf39621..b4b3157 100644 (file)
@@ -14,18 +14,21 @@ namespace TYPO3\CMS\Backend\Http;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\Core\Bootstrap;
 use TYPO3\CMS\Core\FormProtection\BackendFormProtection;
 use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
 use TYPO3\CMS\Core\Exception;
 use TYPO3\CMS\Core\Http\RequestHandlerInterface;
+use TYPO3\CMS\Core\Http\Response;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Extbase\Object\ObjectManager;
 use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Utility\MathUtility;
 
 /**
  * Handles the request for backend modules and wizards
+ * Juggles with $GLOBALS['TBE_MODULES']
  */
 class BackendModuleRequestHandler implements RequestHandlerInterface {
 
@@ -83,17 +86,20 @@ class BackendModuleRequestHandler implements RequestHandlerInterface {
 
                $moduleName = (string)$this->request->getQueryParams()['M'];
                if ($this->isDispatchedModule($moduleName)) {
-                       $isDispatched = $this->dispatchModule($moduleName);
+                       return $this->dispatchModule($moduleName);
                } else {
                        $isDispatched = $this->callTraditionalModule($moduleName);
+                       if (!$isDispatched) {
+                               throw new Exception('No module "' . $moduleName . '" could be found.', 1294585070);
+                       }
                }
-               if ($isDispatched === FALSE) {
-                       throw new Exception('No module "' . $moduleName . '" could be found.', 1294585070);
-               }
+               return NULL;
        }
 
        /**
         * Execute TYPO3 bootstrap
+        *
+        * @return void
         */
        protected function boot() {
                // Evaluate the constant for skipping the BE user check for the bootstrap, will be done without the constant at a later point
@@ -134,14 +140,13 @@ class BackendModuleRequestHandler implements RequestHandlerInterface {
         * @return bool
         */
        protected function isValidModuleRequest() {
-               return
-                       $this->getFormProtection() instanceof BackendFormProtection
-               && $this->getFormProtection()->validateToken((string)$this->request->getQueryParams()['moduleToken'], 'moduleCall', (string)$this->request->getQueryParams()['M']);
+               return $this->getFormProtection() instanceof BackendFormProtection
+                       && $this->getFormProtection()->validateToken((string)$this->request->getQueryParams()['moduleToken'], 'moduleCall', (string)$this->request->getQueryParams()['M']);
        }
 
        /**
-        * A dispatched module, currently only Extbase modules are dispatched,
-        * traditional modules have a module path set.
+        * A dispatched module is used, when no PATH is given.
+        * Traditional modules have a module path set.
         *
         * @param string $moduleName
         * @return bool
@@ -151,23 +156,43 @@ class BackendModuleRequestHandler implements RequestHandlerInterface {
        }
 
        /**
-        * Executes the module dispatcher which calls the module appropriately.
-        * Currently only used by Extbase
+        * Executes the modules configured via Extbase
         *
         * @param string $moduleName
-        * @return bool
+        * @return Response A PSR-7 response object
+        * @throws \RuntimeException
         */
        protected function dispatchModule($moduleName) {
-               if (is_array($this->moduleRegistry['_dispatcher'])) {
-                       foreach ($this->moduleRegistry['_dispatcher'] as $dispatcherClassName) {
-                               $dispatcher = GeneralUtility::makeInstance(ObjectManager::class)->get($dispatcherClassName);
-                               if ($dispatcher->callModule($moduleName) === TRUE) {
-                                       return TRUE;
-                                       break;
-                               }
+               $moduleConfiguration = $this->getModuleConfiguration($moduleName);
+
+               // Check permissions and exit if the user has no permission for entry
+               $this->backendUserAuthentication->modAccess($moduleConfiguration, TRUE);
+               $id = isset($this->request->getQueryParams()['id']) ? $this->request->getQueryParams()['id'] : $this->request->getParsedBody()['id'];
+               if ($id && MathUtility::canBeInterpretedAsInteger($id)) {
+                       // Check page access
+                       $permClause = $this->backendUserAuthentication->getPagePermsClause(TRUE);
+                       $access = is_array(BackendUtility::readPageAccess((int)$id, $permClause));
+                       if (!$access) {
+                               throw new \RuntimeException('You don\'t have access to this page', 1289917924);
                        }
                }
-               return FALSE;
+
+               $configuration = array(
+                       'extensionName' => $moduleConfiguration['extensionName'],
+                       'pluginName' => $moduleName
+               );
+               if (isset($moduleConfiguration['vendorName'])) {
+                       $configuration['vendorName'] = $moduleConfiguration['vendorName'];
+               }
+
+               // Run Extbase
+               $bootstrap = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Core\Bootstrap::class);
+               $content = $bootstrap->run('', $configuration);
+
+               /** @var Response $response */
+               $response = GeneralUtility::makeInstance(Response::class);
+               $response->getBody()->write($content);
+               return $response;
        }
 
        /**
@@ -175,11 +200,19 @@ class BackendModuleRequestHandler implements RequestHandlerInterface {
         * and were previously located within the global scope.
         *
         * @param string $moduleName
-        * @return bool
+        * @return bool Returns TRUE if the module was executed
         */
        protected function callTraditionalModule($moduleName) {
                $moduleBasePath = $this->moduleRegistry['_PATHS'][$moduleName];
-               $GLOBALS['MCONF'] = $moduleConfiguration = $this->getModuleConfiguration($moduleName);
+               // Some modules still rely on this global configuration array in a conf.php file
+               // load configuration from an existing conf.php file inside the same directory
+               if (file_exists($moduleBasePath . 'conf.php')) {
+                       require $moduleBasePath . 'conf.php';
+                       $moduleConfiguration = $MCONF;
+               } else {
+                       $moduleConfiguration = $this->getModuleConfiguration($moduleName);
+               }
+               $GLOBALS['MCONF'] = $moduleConfiguration;
                if (!empty($moduleConfiguration['access'])) {
                        $this->backendUserAuthentication->modAccess($moduleConfiguration, TRUE);
                }
@@ -192,22 +225,17 @@ class BackendModuleRequestHandler implements RequestHandlerInterface {
        }
 
        /**
-        * Returns the module configuration which is either provided in a conf.php file
-        * or during module registration
+        * Returns the module configuration which is provided during module registration
         *
         * @param string $moduleName
         * @return array
+        * @throws \RuntimeException
         */
        protected function getModuleConfiguration($moduleName) {
-               $moduleBasePath = $this->moduleRegistry['_PATHS'][$moduleName];
-               if (file_exists($moduleBasePath . 'conf.php')) {
-                       // Some modules still rely on this global configuration array in a conf.php file
-                       require $moduleBasePath . 'conf.php';
-                       $moduleConfiguration = $MCONF;
-               } else {
-                       $moduleConfiguration = $this->moduleRegistry['_configuration'][$moduleName];
+               if (!isset($this->moduleRegistry['_configuration'][$moduleName])) {
+                       throw new \RuntimeException('Module ' . $moduleName . ' is not configured.', 1289918325);
                }
-               return $moduleConfiguration;
+               return $this->moduleRegistry['_configuration'][$moduleName];
        }
 
 
index 454f259..d48b8a4 100644 (file)
@@ -112,6 +112,7 @@ class ModuleLoader {
                $this->absPathArray = $modulesArray['_PATHS'];
                unset($modulesArray['_PATHS']);
                // Unset the array for calling external backend module dispatchers in typo3/index.php
+               // (unused in Core, but in case some extension still sets this, we unset that)
                unset($modulesArray['_dispatcher']);
                // Unset the array for calling backend modules based on external backend module dispatchers in typo3/index.php
                unset($modulesArray['_configuration']);
index e6fef09..ce34625 100644 (file)
@@ -87,7 +87,6 @@ class BackendModuleRequestHandlerTest extends UnitTestCase {
        public function moduleDispatcherIsCalled() {
                $GLOBALS['TBE_MODULES'] = array(
                        '_PATHS' => array(
-                               '_dispatcher' => array(),
                                'module_fixture' => __DIR__ . '/../Fixtures/ModuleFixture/'
                        )
                );
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-69148-BackendModuleDispatchingRemoved.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-69148-BackendModuleDispatchingRemoved.rst
new file mode 100644 (file)
index 0000000..a369aeb
--- /dev/null
@@ -0,0 +1,27 @@
+=====================================================
+Breaking: #69148 - Backend Module Dispatching removed
+=====================================================
+
+Description
+===========
+
+Dispatching Backend modules through custom dispatchers have been removed. The corresponding Extbase functionality
+called "ModuleRunner" and its Interface have been removed as well.
+
+
+Impact
+======
+
+Any dispatcher registered via ``$TBE_MODULES['_dispatcher']`` is not evaluated anymore.
+
+
+Affected Installations
+======================
+
+All TYPO3 Instances with an extension that registers a custom backend module dispatcher.
+
+
+Migration
+=========
+
+Use a custom RequestHandler.
\ No newline at end of file
diff --git a/typo3/sysext/extbase/Classes/Core/ModuleRunner.php b/typo3/sysext/extbase/Classes/Core/ModuleRunner.php
deleted file mode 100644 (file)
index 767c7cf..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-namespace TYPO3\CMS\Extbase\Core;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Dispatches a request
- */
-class ModuleRunner implements ModuleRunnerInterface {
-
-       /**
-        * @var \TYPO3\CMS\Extbase\Object\ObjectManager
-        */
-       protected $objectManager;
-
-       /**
-        * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager
-        */
-       public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager) {
-               $this->objectManager = $objectManager;
-       }
-
-       /**
-        * This method forwards the call to Bootstrap's run() method. This method is invoked by the BackendModuleRequestHandler
-        * function of TYPO3.
-        *
-        * @param string $moduleSignature
-        * @throws \RuntimeException
-        * @return bool TRUE, if the request request could be dispatched
-        * @see run()
-        */
-       public function callModule($moduleSignature) {
-               if (!isset($GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature])) {
-                       return FALSE;
-               }
-               $moduleConfiguration = $GLOBALS['TBE_MODULES']['_configuration'][$moduleSignature];
-
-               // Check permissions and exit if the user has no permission for entry
-               $GLOBALS['BE_USER']->modAccess($moduleConfiguration, TRUE);
-               $id = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('id');
-               if ($id && \TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($id)) {
-                       // Check page access
-                       $permClause = $GLOBALS['BE_USER']->getPagePermsClause(TRUE);
-                       $access = is_array(\TYPO3\CMS\Backend\Utility\BackendUtility::readPageAccess((int)$id, $permClause));
-                       if (!$access) {
-                               throw new \RuntimeException('You don\'t have access to this page', 1289917924);
-                       }
-               }
-
-               // BACK_PATH is the path from the typo3/ directory from within the
-               // directory containing the controller file. We are using index.php dispatcher
-               // and thus we are already within typo3/ because we call typo3/index.php
-               $GLOBALS['BACK_PATH'] = '';
-               $configuration = array(
-                       'extensionName' => $moduleConfiguration['extensionName'],
-                       'pluginName' => $moduleSignature
-               );
-               if (isset($moduleConfiguration['vendorName'])) {
-                       $configuration['vendorName'] = $moduleConfiguration['vendorName'];
-               }
-
-               $bootstrap = $this->objectManager->get(\TYPO3\CMS\Extbase\Core\BootstrapInterface::class);
-               $content = $bootstrap->run('', $configuration);
-               print $content;
-
-               return TRUE;
-       }
-
-}
diff --git a/typo3/sysext/extbase/Classes/Core/ModuleRunnerInterface.php b/typo3/sysext/extbase/Classes/Core/ModuleRunnerInterface.php
deleted file mode 100644 (file)
index 399b944..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-namespace TYPO3\CMS\Extbase\Core;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Interface for module runners that can execute requests to Extbase controllers in the backend
- */
-interface ModuleRunnerInterface {
-       /**
-        * Initializes and runs a module.
-        *
-        * @param string $moduleSignature
-        * @throws \RuntimeException
-        * @return bool TRUE, if the request request could be dispatched
-        * @see run()
-        */
-       public function callModule($moduleSignature);
-}
index 3d646c5..b52a8d2 100644 (file)
@@ -1,10 +1,6 @@
 <?php
 defined('TYPO3_MODE') or die();
 
-if (TYPO3_MODE === 'BE') {
-       // register Extbase dispatcher for modules
-       $TBE_MODULES['_dispatcher'][] = \TYPO3\CMS\Extbase\Core\ModuleRunnerInterface::class;
-}
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']['tx_reports']['status']['providers']['extbase'][] = \TYPO3\CMS\Extbase\Utility\ExtbaseRequirementsCheckUtility::class;
 
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\TYPO3\CMS\Extbase\Scheduler\Task::class] = array(