From 93dd893fe90d2a17bbd3f939ca398b603170304e Mon Sep 17 00:00:00 2001 From: Benjamin Mack <benni@typo3.org> Date: Mon, 13 Jul 2015 20:44:34 +0200 Subject: [PATCH] [BUGFIX] Add Request Handling for Console The bootstrap functionality for resolving the RequestHandler based on the request object added by the PSR-7 change. The Bootstrap::run() method is now renamed to ->configure() which does not call resolveRequest() anymore. Instead resolveRequest() is called explicitly at a later point inside every Application instance. This way, the Application instance decides what kind of Request object should be instantiated and hands it to the Bootstrap, which in return resolves the RequestHandler. The original RequestHandlerInterface is now moved to the Http/ namespace, and a RequestHandlerInterface for the Console application has been introduced for handling Console requests, based on Symfony Console. Resolves: #68085 Releases: master Change-Id: Ibbc48362739f9849f6e6d9fcadfd2e2a5247f89b Reviewed-on: http://review.typo3.org/41140 Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl> Tested-by: Wouter Wolters <typo3@wouterwolters.nl> Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org> Tested-by: Helmut Hummel <helmut.hummel@typo3.org> Reviewed-by: Benjamin Mack <benni@typo3.org> Tested-by: Benjamin Mack <benni@typo3.org> --- .../backend/Classes/Console/Application.php | 4 +- .../Classes/Console/CliRequestHandler.php | 13 +++-- .../Classes/Http/AjaxRequestHandler.php | 2 +- .../backend/Classes/Http/Application.php | 4 +- .../Http/BackendModuleRequestHandler.php | 3 +- .../backend/Classes/Http/RequestHandler.php | 4 +- .../Console/RequestHandlerInterface.php | 54 +++++++++++++++++++ typo3/sysext/core/Classes/Core/Bootstrap.php | 21 ++++---- .../RequestHandlerInterface.php | 2 +- .../Classes/Http/ServerRequestFactory.php | 2 +- .../frontend/Classes/Http/Application.php | 4 +- .../Classes/Http/EidRequestHandler.php | 2 +- .../frontend/Classes/Http/RequestHandler.php | 2 +- .../install/Classes/Http/Application.php | 9 ++-- .../install/Classes/Http/RequestHandler.php | 2 +- 15 files changed, 93 insertions(+), 35 deletions(-) create mode 100644 typo3/sysext/core/Classes/Console/RequestHandlerInterface.php rename typo3/sysext/core/Classes/{Core => Http}/RequestHandlerInterface.php (97%) diff --git a/typo3/sysext/backend/Classes/Console/Application.php b/typo3/sysext/backend/Classes/Console/Application.php index bca462ee6102..26868fb63b39 100644 --- a/typo3/sysext/backend/Classes/Console/Application.php +++ b/typo3/sysext/backend/Classes/Console/Application.php @@ -58,6 +58,8 @@ class Application implements ApplicationInterface { foreach ($this->availableRequestHandlers as $requestHandler) { $this->bootstrap->registerRequestHandlerImplementation($requestHandler); } + + $this->bootstrap->configure(); } /** @@ -67,7 +69,7 @@ class Application implements ApplicationInterface { * @return void */ public function run(callable $execute = NULL) { - $this->bootstrap->run(); + $this->bootstrap->handleRequest(new \Symfony\Component\Console\Input\ArgvInput()); if ($execute !== NULL) { if ($execute instanceof \Closure) { diff --git a/typo3/sysext/backend/Classes/Console/CliRequestHandler.php b/typo3/sysext/backend/Classes/Console/CliRequestHandler.php index 3e9c24f3f260..6b6119538b16 100644 --- a/typo3/sysext/backend/Classes/Console/CliRequestHandler.php +++ b/typo3/sysext/backend/Classes/Console/CliRequestHandler.php @@ -14,9 +14,8 @@ namespace TYPO3\CMS\Backend\Console; * The TYPO3 project - inspiring people to share! */ -use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Core\Bootstrap; -use TYPO3\CMS\Core\Core\RequestHandlerInterface; +use TYPO3\CMS\Core\Console\RequestHandlerInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -45,10 +44,10 @@ class CliRequestHandler implements RequestHandlerInterface { /** * Handles any commandline request * - * @param ServerRequestInterface $request + * @param \Symfony\Component\Console\Input\InputInterface $request * @return void */ - public function handleRequest(ServerRequestInterface $request) { + public function handleRequest(\Symfony\Component\Console\Input\InputInterface $request) { $commandLineKey = $this->getCommandLineKeyOrDie(); $commandLineScript = $this->getIncludeScriptByCommandLineKey($commandLineKey); @@ -137,12 +136,12 @@ class CliRequestHandler implements RequestHandlerInterface { } /** - * This request handler can handle any CLI request . + * This request handler can handle any CLI request. * - * @param ServerRequestInterface $request + * @param \Symfony\Component\Console\Input\InputInterface $request * @return bool If the request is a CLI request, TRUE otherwise FALSE */ - public function canHandleRequest(ServerRequestInterface $request) { + public function canHandleRequest(\Symfony\Component\Console\Input\InputInterface $request) { return defined('TYPO3_cliMode') && (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_BE) && (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_CLI); } diff --git a/typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php b/typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php index 306d7d2d501f..554ad8fb2de0 100644 --- a/typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php +++ b/typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php @@ -15,7 +15,7 @@ namespace TYPO3\CMS\Backend\Http; */ use TYPO3\CMS\Core\Core\Bootstrap; -use TYPO3\CMS\Core\Core\RequestHandlerInterface; +use TYPO3\CMS\Core\Http\RequestHandlerInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use Psr\Http\Message\ServerRequestInterface; diff --git a/typo3/sysext/backend/Classes/Http/Application.php b/typo3/sysext/backend/Classes/Http/Application.php index 01ebd90ba6ad..b860541aebd2 100644 --- a/typo3/sysext/backend/Classes/Http/Application.php +++ b/typo3/sysext/backend/Classes/Http/Application.php @@ -65,6 +65,8 @@ class Application implements ApplicationInterface { foreach ($this->availableRequestHandlers as $requestHandler) { $this->bootstrap->registerRequestHandlerImplementation($requestHandler); } + + $this->bootstrap->configure(); } /** @@ -74,7 +76,7 @@ class Application implements ApplicationInterface { * @return void */ public function run(callable $execute = NULL) { - $this->bootstrap->run(); + $this->bootstrap->handleRequest(\TYPO3\CMS\Core\Http\ServerRequestFactory::fromGlobals()); if ($execute !== NULL) { if ($execute instanceof \Closure) { diff --git a/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php b/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php index e31d852aad95..de2567134b90 100644 --- a/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php +++ b/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php @@ -18,6 +18,7 @@ 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\Http\RequestHandlerInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Object\ObjectManager; use Psr\Http\Message\ServerRequestInterface; @@ -25,7 +26,7 @@ use Psr\Http\Message\ServerRequestInterface; /** * Handles the request for backend modules and wizards */ -class BackendModuleRequestHandler implements \TYPO3\CMS\Core\Core\RequestHandlerInterface { +class BackendModuleRequestHandler implements RequestHandlerInterface { /** * @var Bootstrap diff --git a/typo3/sysext/backend/Classes/Http/RequestHandler.php b/typo3/sysext/backend/Classes/Http/RequestHandler.php index 489616e4d63e..2860c426baf8 100644 --- a/typo3/sysext/backend/Classes/Http/RequestHandler.php +++ b/typo3/sysext/backend/Classes/Http/RequestHandler.php @@ -15,7 +15,7 @@ namespace TYPO3\CMS\Backend\Http; */ use TYPO3\CMS\Core\Core\Bootstrap; -use TYPO3\CMS\Core\Core\RequestHandlerInterface; +use TYPO3\CMS\Core\Http\RequestHandlerInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -84,7 +84,7 @@ class RequestHandler implements RequestHandlerInterface { /** * This request handler can handle any backend request (but not CLI). * - * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Psr\Http\Message\ServerRequestInterface|\TYPO3\CMS\Core\Console\Request $request * @return bool If the request is not a CLI script, TRUE otherwise FALSE */ public function canHandleRequest(\Psr\Http\Message\ServerRequestInterface $request) { diff --git a/typo3/sysext/core/Classes/Console/RequestHandlerInterface.php b/typo3/sysext/core/Classes/Console/RequestHandlerInterface.php new file mode 100644 index 000000000000..32cf5494bb38 --- /dev/null +++ b/typo3/sysext/core/Classes/Console/RequestHandlerInterface.php @@ -0,0 +1,54 @@ +<?php +namespace TYPO3\CMS\Core\Console; + +/* + * 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 Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * The interface for a request handler for a console-based application + * + * @api + */ +interface RequestHandlerInterface { + + /** + * Handles a raw request + * + * @param InputInterface $request + * @return NULL|OutputInterface + * @api + */ + public function handleRequest(InputInterface $request); + + /** + * Checks if the request handler can handle the given request. + * + * @param InputInterface $request + * @return bool TRUE if it can handle the request, otherwise FALSE + * @api + */ + public function canHandleRequest(InputInterface $request); + + /** + * Returns the priority - how eager the handler is to actually handle the + * request. An integer > 0 means "I want to handle this request" where + * "100" is default. "0" means "I am a fallback solution". + * + * @return int The priority of the request handler + * @api + */ + public function getPriority(); + +} diff --git a/typo3/sysext/core/Classes/Core/Bootstrap.php b/typo3/sysext/core/Classes/Core/Bootstrap.php index 616878bdb8b9..8c88d91465e3 100644 --- a/typo3/sysext/core/Classes/Core/Bootstrap.php +++ b/typo3/sysext/core/Classes/Core/Bootstrap.php @@ -74,7 +74,7 @@ class Bootstrap { /** * A list of all registered request handlers, see the Application class / entry points for the registration - * @var RequestHandlerInterface[] + * @var \TYPO3\CMS\Core\Http\RequestHandlerInterface[]|\TYPO3\CMS\Core\Console\RequestHandlerInterface[] */ protected $availableRequestHandlers = array(); @@ -164,14 +164,13 @@ class Bootstrap { /** * Main entry point called at every request usually from Global scope. Checks if everything is correct, - * and sets up the base request information for a regular request, then - * resolves the RequestHandler which handles the request. + * and loads the Configuration. * * Make sure that the baseSetup() is called before and the class loader is present * * @return Bootstrap */ - public function run() { + public function configure() { $this->startOutputBuffering() ->loadConfigurationAndInitialize() ->loadTypo3LoadedExtAndExtLocalconf(TRUE) @@ -179,8 +178,7 @@ class Bootstrap { ->setFinalCachingFrameworkCacheConfiguration() ->defineLoggingAndExceptionConstants() ->unsetReservedGlobalVariables() - ->initializeTypo3DbGlobal() - ->handleRequest(); + ->initializeTypo3DbGlobal(); return $this; } @@ -259,12 +257,12 @@ class Bootstrap { * Be sure to always have the constants that are defined in $this->defineTypo3RequestTypes() are set, * so most RequestHandlers can check if they can handle the request. * - * @param \Psr\Http\Message\ServerRequestInterface $request - * @return RequestHandlerInterface + * @param \Psr\Http\Message\RequestInterface|\Symfony\Component\Console\Input\InputInterface $request + * @return \TYPO3\CMS\Core\Http\RequestHandlerInterface|\TYPO3\CMS\Core\Console\RequestHandlerInterface * @throws \TYPO3\CMS\Core\Exception * @internal This is not a public API method, do not use in own extensions */ - protected function resolveRequestHandler(\Psr\Http\Message\ServerRequestInterface $request) { + protected function resolveRequestHandler($request) { $suitableRequestHandlers = array(); foreach ($this->availableRequestHandlers as $requestHandlerClassName) { $requestHandler = GeneralUtility::makeInstance($requestHandlerClassName, $this); @@ -287,13 +285,12 @@ class Bootstrap { * Builds a Request instance from the current process, and then resolves the request * through the request handlers depending on Frontend, Backend, CLI etc. * + * @param \Psr\Http\Message\RequestInterface|\Symfony\Component\Console\Input\InputInterface $request * @return Bootstrap * @throws \TYPO3\CMS\Core\Exception * @internal This is not a public API method, do not use in own extensions */ - public function handleRequest() { - // Build the Request object - $request = \TYPO3\CMS\Core\Http\ServerRequestFactory::fromGlobals(); + public function handleRequest($request) { // Resolve request handler that were registered based on the Application $requestHandler = $this->resolveRequestHandler($request); diff --git a/typo3/sysext/core/Classes/Core/RequestHandlerInterface.php b/typo3/sysext/core/Classes/Http/RequestHandlerInterface.php similarity index 97% rename from typo3/sysext/core/Classes/Core/RequestHandlerInterface.php rename to typo3/sysext/core/Classes/Http/RequestHandlerInterface.php index 7af6f4258c55..33c66b67b2e7 100644 --- a/typo3/sysext/core/Classes/Core/RequestHandlerInterface.php +++ b/typo3/sysext/core/Classes/Http/RequestHandlerInterface.php @@ -1,5 +1,5 @@ <?php -namespace TYPO3\CMS\Core\Core; +namespace TYPO3\CMS\Core\Http; /* * This file is part of the TYPO3 CMS project. diff --git a/typo3/sysext/core/Classes/Http/ServerRequestFactory.php b/typo3/sysext/core/Classes/Http/ServerRequestFactory.php index 73014f111d41..85b5aec569d2 100644 --- a/typo3/sysext/core/Classes/Http/ServerRequestFactory.php +++ b/typo3/sysext/core/Classes/Http/ServerRequestFactory.php @@ -125,7 +125,7 @@ class ServerRequestFactory { * Create and return an UploadedFile instance from a $_FILES specification. * * If the specification represents an array of values, this method will - * delegate to normalizeNestedFileSpec() and return that return value. + * recursively resolve uploaded files. * * @param array $value $_FILES structure * @return UploadedFileInterface[]|UploadedFileInterface diff --git a/typo3/sysext/frontend/Classes/Http/Application.php b/typo3/sysext/frontend/Classes/Http/Application.php index 8c3f3d02f121..4ca07a8fc3a0 100644 --- a/typo3/sysext/frontend/Classes/Http/Application.php +++ b/typo3/sysext/frontend/Classes/Http/Application.php @@ -62,6 +62,8 @@ class Application implements ApplicationInterface { foreach ($this->availableRequestHandlers as $requestHandler) { $this->bootstrap->registerRequestHandlerImplementation($requestHandler); } + + $this->bootstrap->configure(); } /** @@ -71,7 +73,7 @@ class Application implements ApplicationInterface { * @return void */ public function run(callable $execute = NULL) { - $this->bootstrap->run(); + $this->bootstrap->handleRequest(\TYPO3\CMS\Core\Http\ServerRequestFactory::fromGlobals()); if ($execute !== NULL) { if ($execute instanceof \Closure) { diff --git a/typo3/sysext/frontend/Classes/Http/EidRequestHandler.php b/typo3/sysext/frontend/Classes/Http/EidRequestHandler.php index 81cb6fb4efca..09dcbc6d9825 100644 --- a/typo3/sysext/frontend/Classes/Http/EidRequestHandler.php +++ b/typo3/sysext/frontend/Classes/Http/EidRequestHandler.php @@ -19,7 +19,7 @@ use TYPO3\CMS\Core\TimeTracker\NullTimeTracker; use TYPO3\CMS\Core\TimeTracker\TimeTracker; use TYPO3\CMS\Frontend\Utility\EidUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Core\RequestHandlerInterface; +use TYPO3\CMS\Core\Http\RequestHandlerInterface; use Psr\Http\Message\ServerRequestInterface; /** diff --git a/typo3/sysext/frontend/Classes/Http/RequestHandler.php b/typo3/sysext/frontend/Classes/Http/RequestHandler.php index b223440ee214..9ecf49836564 100644 --- a/typo3/sysext/frontend/Classes/Http/RequestHandler.php +++ b/typo3/sysext/frontend/Classes/Http/RequestHandler.php @@ -16,7 +16,7 @@ namespace TYPO3\CMS\Frontend\Http; use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; use TYPO3\CMS\Core\Core\Bootstrap; -use TYPO3\CMS\Core\Core\RequestHandlerInterface; +use TYPO3\CMS\Core\Http\RequestHandlerInterface; use TYPO3\CMS\Core\FrontendEditing\FrontendEditingController; use TYPO3\CMS\Core\TimeTracker\NullTimeTracker; use TYPO3\CMS\Core\TimeTracker\TimeTracker; diff --git a/typo3/sysext/install/Classes/Http/Application.php b/typo3/sysext/install/Classes/Http/Application.php index 4a44a26db4fc..bd85360fe3f7 100644 --- a/typo3/sysext/install/Classes/Http/Application.php +++ b/typo3/sysext/install/Classes/Http/Application.php @@ -55,6 +55,10 @@ class Application implements ApplicationInterface { foreach ($this->availableRequestHandlers as $requestHandler) { $this->bootstrap->registerRequestHandlerImplementation($requestHandler); } + + $this->bootstrap + ->startOutputBuffering() + ->loadConfigurationAndInitialize(FALSE, \TYPO3\CMS\Core\Package\FailsafePackageManager::class); } /** @@ -66,10 +70,7 @@ class Application implements ApplicationInterface { * @return void */ public function run(callable $execute = NULL) { - $this->bootstrap - ->startOutputBuffering() - ->loadConfigurationAndInitialize(FALSE, \TYPO3\CMS\Core\Package\FailsafePackageManager::class) - ->handleRequest(); + $this->bootstrap->handleRequest(\TYPO3\CMS\Core\Http\ServerRequestFactory::fromGlobals()); if ($execute !== NULL) { if ($execute instanceof \Closure) { diff --git a/typo3/sysext/install/Classes/Http/RequestHandler.php b/typo3/sysext/install/Classes/Http/RequestHandler.php index 6ccce1e3474e..3eae52f0306e 100644 --- a/typo3/sysext/install/Classes/Http/RequestHandler.php +++ b/typo3/sysext/install/Classes/Http/RequestHandler.php @@ -16,7 +16,7 @@ namespace TYPO3\CMS\Install\Http; use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Core\Bootstrap; -use TYPO3\CMS\Core\Core\RequestHandlerInterface; +use TYPO3\CMS\Core\Http\RequestHandlerInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; /** -- GitLab