From 0295db1fe591cc13cd28feacffb060e86978562b Mon Sep 17 00:00:00 2001
From: Helmut Hummel <helmut.hummel@typo3.org>
Date: Mon, 8 Dec 2014 16:21:56 +0100
Subject: [PATCH] [TASK] Refactor module dispatcher to RequestHandler

In order to move the mod.php global logic into
a unified way, the global code is moved to its
own RequestHandler for modules.

Releases: master
Resolves: #65452
Change-Id: Ic1dedaf7d98b460739da9cb33dcbbf5772ed05d4
Reviewed-on: http://review.typo3.org/37430
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Benjamin Mack <benni@typo3.org>
Tested-by: Benjamin Mack <benni@typo3.org>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 typo3/mod.php                                 |  49 +----
 .../Classes/BackendModuleRequestHandler.php   | 208 ++++++++++++++++++
 .../Classes/Module/AbstractFunctionModule.php |   4 +-
 .../Classes/Module/BaseScriptClass.php        |  10 +-
 typo3/sysext/backend/Modules/Layout/index.php |  10 +-
 .../Modules/NewContentElement/index.php       |   8 +-
 .../Unit/BackendModuleRequestHandlerTest.php  |  98 +++++++++
 .../Unit/Fixtures/ModuleFixture/conf.php      |   3 +
 .../Unit/Fixtures/ModuleFixture/index.php     |   2 +
 typo3/sysext/cms/layout/db_layout.php         |  10 +-
 typo3/sysext/cms/layout/db_new_content_el.php |   8 +-
 typo3/sysext/core/Classes/Core/Bootstrap.php  |   1 +
 typo3/sysext/cshmanual/mod/index.php          |   8 +-
 typo3/sysext/dbal/mod1/index.php              |   8 +-
 typo3/sysext/filelist/mod1/index.php          |   8 +-
 .../frontend/Resources/PHP/Eid/ShowPic.php    |   4 +-
 typo3/sysext/func/mod1/index.php              |  12 +-
 typo3/sysext/impexp/app/index.php             |   8 +-
 typo3/sysext/info/mod1/index.php              |  12 +-
 typo3/sysext/lowlevel/config/index.php        |   8 +-
 typo3/sysext/lowlevel/dbint/index.php         |   8 +-
 .../Classes/RecordList/DatabaseRecordList.php |   3 +
 typo3/sysext/recordlist/mod1/index.php        |  10 +-
 .../rtehtmlarea/Modules/BrowseLinks/index.php |   6 +-
 .../rtehtmlarea/Modules/ParseHtml/index.php   |   8 +-
 .../rtehtmlarea/Modules/SelectImage/index.php |   6 +-
 .../Modules/UserElements/index.php            |   8 +-
 typo3/sysext/scheduler/mod1/index.php         |   8 +-
 typo3/sysext/setup/mod/index.php              |  12 +-
 typo3/sysext/taskcenter/task/index.php        |   6 +-
 typo3/sysext/tstemplate/ts/index.php          |  12 +-
 typo3/sysext/version/cm1/index.php            |   8 +-
 typo3/thumbs.php                              |   6 +-
 33 files changed, 431 insertions(+), 149 deletions(-)
 create mode 100644 typo3/sysext/backend/Classes/BackendModuleRequestHandler.php
 create mode 100644 typo3/sysext/backend/Tests/Unit/BackendModuleRequestHandlerTest.php
 create mode 100644 typo3/sysext/backend/Tests/Unit/Fixtures/ModuleFixture/conf.php
 create mode 100644 typo3/sysext/backend/Tests/Unit/Fixtures/ModuleFixture/index.php

diff --git a/typo3/mod.php b/typo3/mod.php
index 6e09e2802ad6..b5b99dbf5f19 100644
--- a/typo3/mod.php
+++ b/typo3/mod.php
@@ -1,4 +1,6 @@
 <?php
+namespace TYPO3\CMS\Backend;
+
 /*
  * This file is part of the TYPO3 CMS project.
  *
@@ -13,45 +15,10 @@
  */
 
 /**
- * Module Dispatch script
- *
- * @author Kasper Skårhøj <kasperYYYY@typo3.com>
+ * Module entry script
+ * Main entry point for all modules (wizards, backend modules, module functions etc)
+ * which usually uses the BackendModuleRequestHandler
  */
-unset($MCONF);
-require __DIR__ . '/init.php';
-// Find module path:
-$moduleName = (string)\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('M');
-$isDispatched = FALSE;
-$formProtection = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get();
-if (!$formProtection->validateToken(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('moduleToken'), 'moduleCall', $moduleName)) {
-	throw new UnexpectedValueException('Invalid form/module token detected. Access Denied!', 1392409507);
-}
-if ($temp_path = $GLOBALS['TBE_MODULES']['_PATHS'][$moduleName]) {
-	if (file_exists($temp_path . 'conf.php')) {
-		require $temp_path . 'conf.php';
-		$moduleConfiguration = $GLOBALS['MCONF'];
-	} else {
-		$moduleConfiguration = $GLOBALS['TBE_MODULES']['_configuration'][$moduleName];
-	}
-	if (!empty($moduleConfiguration['access'])) {
-		$GLOBALS['BE_USER']->modAccess($moduleConfiguration, TRUE);
-	}
-
-	$BACK_PATH = '';
-	require $temp_path . 'index.php';
-	$isDispatched = TRUE;
-} else {
-	if (is_array($GLOBALS['TBE_MODULES']['_dispatcher'])) {
-		foreach ($GLOBALS['TBE_MODULES']['_dispatcher'] as $dispatcherClassName) {
-			$dispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class)->get($dispatcherClassName);
-			if ($dispatcher->callModule($moduleName) === TRUE) {
-				$isDispatched = TRUE;
-				break;
-			}
-		}
-	}
-}
-if ($isDispatched === FALSE) {
-	throw new UnexpectedValueException('No module "' . htmlspecialchars($moduleName) . '" could be found.', 1294585070);
-}
-\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->shutdown();
+define('TYPO3_MODE', 'BE');
+require __DIR__ . '/sysext/core/Classes/Core/Bootstrap.php';
+\TYPO3\CMS\Core\Core\Bootstrap::getInstance()->run('typo3/')->shutdown();
diff --git a/typo3/sysext/backend/Classes/BackendModuleRequestHandler.php b/typo3/sysext/backend/Classes/BackendModuleRequestHandler.php
new file mode 100644
index 000000000000..6d40660a33fa
--- /dev/null
+++ b/typo3/sysext/backend/Classes/BackendModuleRequestHandler.php
@@ -0,0 +1,208 @@
+<?php
+namespace TYPO3\CMS\Backend;
+
+/*
+ * 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!
+ */
+
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
+use TYPO3\CMS\Core\Exception;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Object\ObjectManager;
+
+/**
+ * Handles the request for backend modules and wizards
+ */
+class BackendModuleRequestHandler implements \TYPO3\CMS\Core\Core\RequestHandlerInterface {
+
+	/**
+	 * @var Bootstrap
+	 */
+	protected $bootstrap;
+
+	/**
+	 * @var array
+	 */
+	protected $moduleRegistry = array();
+
+	/**
+	 * @var BackendUserAuthentication
+	 */
+	protected $backendUserAuthentication;
+
+	/**
+	 * @param Bootstrap $bootstrap The TYPO3 core bootstrap
+	 */
+	public function __construct(Bootstrap $bootstrap) {
+		$this->bootstrap = $bootstrap;
+	}
+
+	/**
+	 * Handles the request, evaluating the configuration and executes the module accordingly
+	 *
+	 * @throws Exception
+	 */
+	public function handleRequest() {
+		$this->boot();
+
+		$this->moduleRegistry = $GLOBALS['TBE_MODULES'];
+
+		if (!$this->isValidModuleRequest()) {
+			throw new Exception('The CSRF protection token for the requested module is missing or invalid', 1417988921);
+		}
+
+		// Set to empty as it is not needed / always coming from typo3/mod.php
+		$GLOBALS['BACK_PATH'] = '';
+
+		$this->backendUserAuthentication = $GLOBALS['BE_USER'];
+
+		$moduleName = (string)GeneralUtility::_GET('M');
+		if ($this->isDispatchedModule($moduleName)) {
+			$isDispatched = $this->dispatchModule($moduleName);
+		} else {
+			$isDispatched = $this->callTraditionalModule($moduleName);
+		}
+		if ($isDispatched === FALSE) {
+			throw new Exception('No module "' . $moduleName . '" could be found.', 1294585070);
+		}
+	}
+
+	/**
+	 * Execute TYPO3 bootstrap
+	 */
+	protected function boot() {
+		$this->bootstrap->checkLockedBackendAndRedirectOrDie()
+			->checkBackendIpOrDie()
+			->checkSslBackendAndRedirectIfNeeded()
+			->checkValidBrowserOrDie()
+			->loadExtensionTables(TRUE)
+			->initializeSpriteManager()
+			->initializeBackendUser()
+			->initializeBackendAuthentication()
+			->initializeLanguageObject()
+			->initializeBackendTemplate()
+			->endOutputBufferingAndCleanPreviousOutput()
+			->initializeOutputCompression()
+			->sendHttpHeaders();
+	}
+
+	/**
+	 * This request handler can handle any backend request coming from mod.php
+	 *
+	 * @return bool
+	 */
+	public function canHandleRequest() {
+		return (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_BE) && !empty((string)GeneralUtility::_GET('M'));
+	}
+
+	/**
+	 * Checks if all parameters are met.
+	 *
+	 * @return bool
+	 */
+	protected function isValidModuleRequest() {
+		return $this->getFormProtection()->validateToken((string)GeneralUtility::_GP('moduleToken'), 'moduleCall', (string)GeneralUtility::_GET('M'));
+	}
+
+	/**
+	 * A dispatched module, currently only Extbase modules are dispatched,
+	 * traditional modules have a module path set.
+	 *
+	 * @param string $moduleName
+	 * @return bool
+	 */
+	protected function isDispatchedModule($moduleName) {
+		return empty($this->moduleRegistry['_PATHS'][$moduleName]);
+	}
+
+	/**
+	 * Executes the module dispatcher which calls the module appropriately.
+	 * Currently only used by Extbase
+	 *
+	 * @param string $moduleName
+	 * @return bool
+	 */
+	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;
+				}
+			}
+		}
+		return FALSE;
+	}
+
+	/**
+	 * Calls traditional modules which are identified by having a index.php in their directory
+	 * and were previously located within the global scope.
+	 *
+	 * @param string $moduleName
+	 * @return bool
+	 */
+	protected function callTraditionalModule($moduleName) {
+		$moduleBasePath = $this->moduleRegistry['_PATHS'][$moduleName];
+		$GLOBALS['MCONF'] = $moduleConfiguration = $this->getModuleConfiguration($moduleName);
+		if (!empty($moduleConfiguration['access'])) {
+			$this->backendUserAuthentication->modAccess($moduleConfiguration, TRUE);
+		}
+		if (file_exists($moduleBasePath . 'index.php')) {
+			global $SOBE;
+			require $moduleBasePath . 'index.php';
+			return TRUE;
+		}
+		return FALSE;
+	}
+
+	/**
+	 * Returns the module configuration which is either provided in a conf.php file
+	 * or during module registration
+	 *
+	 * @param string $moduleName
+	 * @return array
+	 */
+	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];
+		}
+		return $moduleConfiguration;
+	}
+
+
+	/**
+	 * Returns the priority - how eager the handler is to actually handle the request.
+	 *
+	 * @return int The priority of the request handler.
+	 */
+	public function getPriority() {
+		return 90;
+	}
+
+	/**
+	 * Wrapper method for static form protection utility
+	 *
+	 * @return \TYPO3\CMS\Core\FormProtection\AbstractFormProtection
+	 */
+	protected function getFormProtection() {
+		return FormProtectionFactory::get();
+	}
+
+}
diff --git a/typo3/sysext/backend/Classes/Module/AbstractFunctionModule.php b/typo3/sysext/backend/Classes/Module/AbstractFunctionModule.php
index 342da74e8f6f..991c95cafe50 100644
--- a/typo3/sysext/backend/Classes/Module/AbstractFunctionModule.php
+++ b/typo3/sysext/backend/Classes/Module/AbstractFunctionModule.php
@@ -78,8 +78,8 @@ use TYPO3\CMS\Lang\LanguageService;
  * times inclusion sections in their index.php scripts. For example (from web_func):
  *
  * Make instance:
- * $SOBE = GeneralUtility::makeInstance(\TYPO3\CMS\Func\Controller\PageFunctionsController::class);
- * $SOBE->init();
+ * $GLOBALS['SOBE'] = GeneralUtility::makeInstance(\TYPO3\CMS\Func\Controller\PageFunctionsController::class);
+ * $GLOBALS['SOBE']->init();
  *
  * Anyways, the final interesting thing is to see what the framework
  * "func_wizard" actually does:
diff --git a/typo3/sysext/backend/Classes/Module/BaseScriptClass.php b/typo3/sysext/backend/Classes/Module/BaseScriptClass.php
index a5f753d43889..ae85902723e9 100644
--- a/typo3/sysext/backend/Classes/Module/BaseScriptClass.php
+++ b/typo3/sysext/backend/Classes/Module/BaseScriptClass.php
@@ -60,17 +60,17 @@ use TYPO3\CMS\Lang\LanguageService;
  * }
  *
  * MAKE INSTANCE OF THE SCRIPT CLASS AND CALL init()
- * $SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\Vendor\Prototype\Controller\PrototypeController::class);
- * $SOBE->init();
+ * $GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\Vendor\Prototype\Controller\PrototypeController::class);
+ * $GLOBALS['SOBE']->init();
  *
  *
  * THEN WE WILL CHECK IF THERE IS A 'SUBMODULE' REGISTERED TO BE INITIALIZED AS WELL:
- * $SOBE->checkExtObj();
+ * $GLOBALS['SOBE']->checkExtObj();
  *
  * THEN WE CALL THE main() METHOD AND THIS SHOULD SPARK THE CREATION OF THE MODULE OUTPUT.
- * $SOBE->main();
+ * $GLOBALS['SOBE']->main();
  * FINALLY THE printContent() FUNCTION WILL OUTPUT THE ACCUMULATED CONTENT
- * $SOBE->printContent();
+ * $GLOBALS['SOBE']->printContent();
  *
  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
diff --git a/typo3/sysext/backend/Modules/Layout/index.php b/typo3/sysext/backend/Modules/Layout/index.php
index 19596d013910..1eea8b49a704 100644
--- a/typo3/sysext/backend/Modules/Layout/index.php
+++ b/typo3/sysext/backend/Modules/Layout/index.php
@@ -90,8 +90,8 @@ class ext_posMap extends \TYPO3\CMS\Backend\Tree\View\PagePositionMap {
 
 }
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\PageLayoutController::class);
-$SOBE->init();
-$SOBE->clearCache();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\PageLayoutController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->clearCache();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/backend/Modules/NewContentElement/index.php b/typo3/sysext/backend/Modules/NewContentElement/index.php
index a21ba895a243..626251cf019c 100644
--- a/typo3/sysext/backend/Modules/NewContentElement/index.php
+++ b/typo3/sysext/backend/Modules/NewContentElement/index.php
@@ -52,7 +52,7 @@ class ext_posMap extends \TYPO3\CMS\Backend\Tree\View\PagePositionMap {
 
 }
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\ContentElement\NewContentElementController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
\ No newline at end of file
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\ContentElement\NewContentElementController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
\ No newline at end of file
diff --git a/typo3/sysext/backend/Tests/Unit/BackendModuleRequestHandlerTest.php b/typo3/sysext/backend/Tests/Unit/BackendModuleRequestHandlerTest.php
new file mode 100644
index 000000000000..6bb5d0f1a0cc
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/BackendModuleRequestHandlerTest.php
@@ -0,0 +1,98 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Unit;
+
+/*
+ * 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!
+ */
+
+use PHPUnit_Framework_MockObject_MockObject;
+use TYPO3\CMS\Backend\BackendModuleRequestHandler;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Tests\AccessibleObjectInterface;
+use TYPO3\CMS\Core\Tests\UnitTestCase;
+
+/**
+ * Class BackendModuleRequestHandlerTest
+ */
+class BackendModuleRequestHandlerTest extends UnitTestCase {
+
+	/**
+	 * @var BackendModuleRequestHandler|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface
+	 */
+	protected $subject;
+
+	/**
+	 * @var \TYPO3\CMS\Core\FormProtection\AbstractFormProtection|PHPUnit_Framework_MockObject_MockObject
+	 */
+	protected $formProtectionMock;
+
+	public function setUp() {
+		$this->formProtectionMock = $this->getMock('AbstractFormProtection', array('validateToken'));
+		$this->subject = $this->getAccessibleMock(BackendModuleRequestHandler::class, array('boot', 'getFormProtection'), array(), '', FALSE);
+	}
+
+	/**
+	 * @test
+	 * @expectedException \InvalidArgumentException
+	 * @expectedExceptionCode 1425236663
+	 */
+	public function moduleIndexIsCalled() {
+		$GLOBALS['TBE_MODULES'] = array(
+			'_PATHS' => array(
+				'module_fixture' => __DIR__ . '/Fixtures/ModuleFixture/'
+			)
+		);
+		$_GET['M'] = 'module_fixture';
+
+		$this->formProtectionMock->expects($this->once())->method('validateToken')->will($this->returnValue(TRUE));
+		$this->subject->expects($this->once())->method('boot');
+		$this->subject->expects($this->once())->method('getFormProtection')->will($this->returnValue($this->formProtectionMock));
+
+		$this->subject->handleRequest();
+	}
+
+	/**
+	 * @test
+	 * @expectedException \TYPO3\CMS\Core\Exception
+	 * @expectedExceptionCode 1417988921
+	 */
+	public function throwsExceptionIfTokenIsInvalid() {
+		$this->formProtectionMock->expects($this->once())->method('validateToken')->will($this->returnValue(FALSE));
+		$this->subject->expects($this->once())->method('boot');
+		$this->subject->expects($this->once())->method('getFormProtection')->will($this->returnValue($this->formProtectionMock));
+
+		$this->subject->handleRequest();
+	}
+
+	/**
+	 * @test
+	 * @expectedException \InvalidArgumentException
+	 * @expectedExceptionCode 1425236663
+	 */
+	public function moduleDispatcherIsCalled() {
+		$GLOBALS['TBE_MODULES'] = array(
+			'_PATHS' => array(
+				'_dispatcher' => array(),
+				'module_fixture' => __DIR__ . '/Fixtures/ModuleFixture/'
+			)
+		);
+		$_GET['M'] = 'module_fixture';
+
+		$this->formProtectionMock->expects($this->once())->method('validateToken')->will($this->returnValue(TRUE));
+		$this->subject->expects($this->once())->method('boot');
+		$this->subject->expects($this->once())->method('getFormProtection')->will($this->returnValue($this->formProtectionMock));
+
+		$this->subject->handleRequest();
+	}
+
+}
diff --git a/typo3/sysext/backend/Tests/Unit/Fixtures/ModuleFixture/conf.php b/typo3/sysext/backend/Tests/Unit/Fixtures/ModuleFixture/conf.php
new file mode 100644
index 000000000000..2ea74965f9de
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Fixtures/ModuleFixture/conf.php
@@ -0,0 +1,3 @@
+<?php
+$MCONF = array();
+$MCONF['name'] = 'module_fixture';
\ No newline at end of file
diff --git a/typo3/sysext/backend/Tests/Unit/Fixtures/ModuleFixture/index.php b/typo3/sysext/backend/Tests/Unit/Fixtures/ModuleFixture/index.php
new file mode 100644
index 000000000000..5a84e7cbdf62
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Fixtures/ModuleFixture/index.php
@@ -0,0 +1,2 @@
+<?php
+throw new \InvalidArgumentException('ModuleFixture loaded', 1425236663);
\ No newline at end of file
diff --git a/typo3/sysext/cms/layout/db_layout.php b/typo3/sysext/cms/layout/db_layout.php
index 7cc360c213b2..b9fc03a5b93d 100644
--- a/typo3/sysext/cms/layout/db_layout.php
+++ b/typo3/sysext/cms/layout/db_layout.php
@@ -109,8 +109,8 @@ class ext_posMap extends \TYPO3\CMS\Backend\Tree\View\PagePositionMap {
 	'The page layout class is moved to an own module. Please use BackendUtility::getModuleUrl(\'web_layout\') to link to db_layout.php. This script will be removed with version TYPO3 CMS 8.'
 );
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\PageLayoutController::class);
-$SOBE->init();
-$SOBE->clearCache();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\PageLayoutController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->clearCache();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/cms/layout/db_new_content_el.php b/typo3/sysext/cms/layout/db_new_content_el.php
index 9fd0d46f6c3e..0b70614f39d5 100644
--- a/typo3/sysext/cms/layout/db_new_content_el.php
+++ b/typo3/sysext/cms/layout/db_new_content_el.php
@@ -75,7 +75,7 @@ class ext_posMap extends \TYPO3\CMS\Backend\Tree\View\PagePositionMap {
 	'The new element class is moved to an own module. Please use BackendUtility::getModuleUrl(\'new_content_element\') to link to db_new_content_el.php. This script will be removed with version 8.'
 );
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\ContentElement\NewContentElementController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\ContentElement\NewContentElementController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/core/Classes/Core/Bootstrap.php b/typo3/sysext/core/Classes/Core/Bootstrap.php
index 2af75563701e..18f80f884691 100644
--- a/typo3/sysext/core/Classes/Core/Bootstrap.php
+++ b/typo3/sysext/core/Classes/Core/Bootstrap.php
@@ -293,6 +293,7 @@ class Bootstrap {
 		} elseif (TYPO3_MODE == 'BE') {
 			$this->availableRequestHandlers = array(
 				\TYPO3\CMS\Backend\RequestHandler::class,
+				\TYPO3\CMS\Backend\BackendModuleRequestHandler::class,
 				\TYPO3\CMS\Backend\AjaxRequestHandler::class,
 				\TYPO3\CMS\Backend\CliRequestHandler::class
 			);
diff --git a/typo3/sysext/cshmanual/mod/index.php b/typo3/sysext/cshmanual/mod/index.php
index 68c6af0e2b45..2a90f47e1f92 100644
--- a/typo3/sysext/cshmanual/mod/index.php
+++ b/typo3/sysext/cshmanual/mod/index.php
@@ -11,7 +11,7 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Cshmanual\Controller\HelpModuleController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
\ No newline at end of file
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Cshmanual\Controller\HelpModuleController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
\ No newline at end of file
diff --git a/typo3/sysext/dbal/mod1/index.php b/typo3/sysext/dbal/mod1/index.php
index 0eb793f4be08..37604690644c 100644
--- a/typo3/sysext/dbal/mod1/index.php
+++ b/typo3/sysext/dbal/mod1/index.php
@@ -21,7 +21,7 @@
 $LANG->includeLLFile('EXT:dbal/mod1/locallang.xlf');
 $BE_USER->modAccess($MCONF, 1);
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Dbal\Controller\ModuleController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Dbal\Controller\ModuleController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/filelist/mod1/index.php b/typo3/sysext/filelist/mod1/index.php
index 5df185d43bf5..88cdfe72670b 100644
--- a/typo3/sysext/filelist/mod1/index.php
+++ b/typo3/sysext/filelist/mod1/index.php
@@ -15,7 +15,7 @@
 /**
  * Web>File: File listing
  */
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Filelist\Controller\FileListController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Filelist\Controller\FileListController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/frontend/Resources/PHP/Eid/ShowPic.php b/typo3/sysext/frontend/Resources/PHP/Eid/ShowPic.php
index 728d20547010..85bb4e5121b0 100644
--- a/typo3/sysext/frontend/Resources/PHP/Eid/ShowPic.php
+++ b/typo3/sysext/frontend/Resources/PHP/Eid/ShowPic.php
@@ -34,5 +34,5 @@ if (!defined('PATH_typo3conf')) {
 }
 
 // Make instance:
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Controller\ShowImageController::class);
-$SOBE->execute();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Controller\ShowImageController::class);
+$GLOBALS['SOBE']->execute();
diff --git a/typo3/sysext/func/mod1/index.php b/typo3/sysext/func/mod1/index.php
index fc55f3fec05e..55f862e007c8 100644
--- a/typo3/sysext/func/mod1/index.php
+++ b/typo3/sysext/func/mod1/index.php
@@ -20,13 +20,13 @@
  */
 
 /** @var $SOBE \TYPO3\CMS\Func\Controller\PageFunctionsController */
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Func\Controller\PageFunctionsController::class);
-$SOBE->init();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Func\Controller\PageFunctionsController::class);
+$GLOBALS['SOBE']->init();
 
 // Checking for first level external objects
-$SOBE->checkExtObj();
+$GLOBALS['SOBE']->checkExtObj();
 
 // Checking second level external objects
-$SOBE->checkSubExtObj();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE']->checkSubExtObj();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/impexp/app/index.php b/typo3/sysext/impexp/app/index.php
index 3f3b0c25cc20..93065f9db4c8 100644
--- a/typo3/sysext/impexp/app/index.php
+++ b/typo3/sysext/impexp/app/index.php
@@ -46,7 +46,7 @@
  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Impexp\Controller\ImportExportController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Impexp\Controller\ImportExportController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/info/mod1/index.php b/typo3/sysext/info/mod1/index.php
index e89f32cfa6bb..bfe3b996da61 100644
--- a/typo3/sysext/info/mod1/index.php
+++ b/typo3/sysext/info/mod1/index.php
@@ -18,13 +18,13 @@
  *
  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Info\Controller\InfoModuleController::class);
-$SOBE->init();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Info\Controller\InfoModuleController::class);
+$GLOBALS['SOBE']->init();
 
 // Checking for first level external objects
-$SOBE->checkExtObj();
+$GLOBALS['SOBE']->checkExtObj();
 
 // Checking second level external objects
-$SOBE->checkSubExtObj();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE']->checkSubExtObj();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/lowlevel/config/index.php b/typo3/sysext/lowlevel/config/index.php
index bf14dcb98935..a34ecd781112 100644
--- a/typo3/sysext/lowlevel/config/index.php
+++ b/typo3/sysext/lowlevel/config/index.php
@@ -20,7 +20,7 @@
  * @author Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Lowlevel\View\ConfigurationView::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Lowlevel\View\ConfigurationView::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/lowlevel/dbint/index.php b/typo3/sysext/lowlevel/dbint/index.php
index a685ceea6623..1fe3908d08e5 100644
--- a/typo3/sysext/lowlevel/dbint/index.php
+++ b/typo3/sysext/lowlevel/dbint/index.php
@@ -21,7 +21,7 @@
  * @coauthor Jo Hasenau <info@cybercraft.de>
  */
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Lowlevel\View\DatabaseIntegrityView::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Lowlevel\View\DatabaseIntegrityView::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php
index 00577e4b9321..05967b16dbdd 100644
--- a/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php
+++ b/typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php
@@ -14,7 +14,10 @@ namespace TYPO3\CMS\Recordlist\RecordList;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Backend\Module\BaseScriptClass;
 use TYPO3\CMS\Backend\RecordList\RecordListGetTableHookInterface;
+use TYPO3\CMS\Backend\Template\DocumentTemplate;
+use TYPO3\CMS\Core\Database\DatabaseConnection;
 use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageService;
 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
diff --git a/typo3/sysext/recordlist/mod1/index.php b/typo3/sysext/recordlist/mod1/index.php
index 3fec9ef011aa..e1cfd978e8e6 100644
--- a/typo3/sysext/recordlist/mod1/index.php
+++ b/typo3/sysext/recordlist/mod1/index.php
@@ -25,8 +25,8 @@
  */
 \TYPO3\CMS\Backend\Utility\BackendUtility::lockRecords();
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Recordlist\RecordList::class);
-$SOBE->init();
-$SOBE->clearCache();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Recordlist\RecordList::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->clearCache();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/rtehtmlarea/Modules/BrowseLinks/index.php b/typo3/sysext/rtehtmlarea/Modules/BrowseLinks/index.php
index b7623e59e0f2..6931110c2c6c 100644
--- a/typo3/sysext/rtehtmlarea/Modules/BrowseLinks/index.php
+++ b/typo3/sysext/rtehtmlarea/Modules/BrowseLinks/index.php
@@ -24,6 +24,6 @@
  */
 
 // Make instance:
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rtehtmlarea\Controller\BrowseLinksController::class);
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rtehtmlarea\Controller\BrowseLinksController::class);
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/rtehtmlarea/Modules/ParseHtml/index.php b/typo3/sysext/rtehtmlarea/Modules/ParseHtml/index.php
index 4a4eb989bfed..399b43c41528 100644
--- a/typo3/sysext/rtehtmlarea/Modules/ParseHtml/index.php
+++ b/typo3/sysext/rtehtmlarea/Modules/ParseHtml/index.php
@@ -19,7 +19,7 @@
  */
 
 // Make instance:
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rtehtmlarea\Controller\ParseHtmlController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rtehtmlarea\Controller\ParseHtmlController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/rtehtmlarea/Modules/SelectImage/index.php b/typo3/sysext/rtehtmlarea/Modules/SelectImage/index.php
index f536fb1450ea..3381d1325f58 100644
--- a/typo3/sysext/rtehtmlarea/Modules/SelectImage/index.php
+++ b/typo3/sysext/rtehtmlarea/Modules/SelectImage/index.php
@@ -20,6 +20,6 @@
  */
 
 // Make instance:
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rtehtmlarea\Controller\SelectImageController::class);
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rtehtmlarea\Controller\SelectImageController::class);
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/rtehtmlarea/Modules/UserElements/index.php b/typo3/sysext/rtehtmlarea/Modules/UserElements/index.php
index a18fc19153b3..0466ff1d706d 100644
--- a/typo3/sysext/rtehtmlarea/Modules/UserElements/index.php
+++ b/typo3/sysext/rtehtmlarea/Modules/UserElements/index.php
@@ -20,7 +20,7 @@
  */
 
 // Make instance:
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rtehtmlarea\Controller\UserElementsController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rtehtmlarea\Controller\UserElementsController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/scheduler/mod1/index.php b/typo3/sysext/scheduler/mod1/index.php
index c96e21fb8791..e6e39eb17d55 100644
--- a/typo3/sysext/scheduler/mod1/index.php
+++ b/typo3/sysext/scheduler/mod1/index.php
@@ -12,7 +12,7 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\Controller\SchedulerModuleController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->render();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Scheduler\Controller\SchedulerModuleController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->render();
diff --git a/typo3/sysext/setup/mod/index.php b/typo3/sysext/setup/mod/index.php
index 638faeb5c9db..e279a234b769 100644
--- a/typo3/sysext/setup/mod/index.php
+++ b/typo3/sysext/setup/mod/index.php
@@ -12,9 +12,9 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Setup\Controller\SetupModuleController::class);
-$SOBE->simulateUser();
-$SOBE->storeIncomingData();
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Setup\Controller\SetupModuleController::class);
+$GLOBALS['SOBE']->simulateUser();
+$GLOBALS['SOBE']->storeIncomingData();
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/taskcenter/task/index.php b/typo3/sysext/taskcenter/task/index.php
index 8263c741b01c..a641733352d2 100644
--- a/typo3/sysext/taskcenter/task/index.php
+++ b/typo3/sysext/taskcenter/task/index.php
@@ -12,6 +12,6 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Taskcenter\Controller\TaskModuleController::class);
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Taskcenter\Controller\TaskModuleController::class);
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/tstemplate/ts/index.php b/typo3/sysext/tstemplate/ts/index.php
index 7c7e17701317..4215698bd4ec 100644
--- a/typo3/sysext/tstemplate/ts/index.php
+++ b/typo3/sysext/tstemplate/ts/index.php
@@ -12,11 +12,11 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController::class);
-$SOBE->init();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateModuleController::class);
+$GLOBALS['SOBE']->init();
 
 // Checking for first level external objects
-$SOBE->checkExtObj();
-$SOBE->clearCache();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE']->checkExtObj();
+$GLOBALS['SOBE']->clearCache();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/sysext/version/cm1/index.php b/typo3/sysext/version/cm1/index.php
index b9a2bcfcc08b..eed2deb2e111 100644
--- a/typo3/sysext/version/cm1/index.php
+++ b/typo3/sysext/version/cm1/index.php
@@ -12,7 +12,7 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Version\Controller\VersionModuleController::class);
-$SOBE->init();
-$SOBE->main();
-$SOBE->printContent();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Version\Controller\VersionModuleController::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
+$GLOBALS['SOBE']->printContent();
diff --git a/typo3/thumbs.php b/typo3/thumbs.php
index b831ff5d4093..071f727b21e6 100644
--- a/typo3/thumbs.php
+++ b/typo3/thumbs.php
@@ -21,6 +21,6 @@
 require __DIR__ . '/init.php';
 
 // Make instance:
-$SOBE = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\View\ThumbnailView::class);
-$SOBE->init();
-$SOBE->main();
+$GLOBALS['SOBE'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\View\ThumbnailView::class);
+$GLOBALS['SOBE']->init();
+$GLOBALS['SOBE']->main();
-- 
GitLab