[BUGFIX] Add Request Handling for Console 40/41140/2
authorBenjamin Mack <benni@typo3.org>
Mon, 13 Jul 2015 18:44:34 +0000 (20:44 +0200)
committerBenjamin Mack <benni@typo3.org>
Tue, 14 Jul 2015 12:39:02 +0000 (14:39 +0200)
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>
16 files changed:
typo3/sysext/backend/Classes/Console/Application.php
typo3/sysext/backend/Classes/Console/CliRequestHandler.php
typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php
typo3/sysext/backend/Classes/Http/Application.php
typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php
typo3/sysext/backend/Classes/Http/RequestHandler.php
typo3/sysext/core/Classes/Console/RequestHandlerInterface.php [new file with mode: 0644]
typo3/sysext/core/Classes/Core/Bootstrap.php
typo3/sysext/core/Classes/Core/RequestHandlerInterface.php [deleted file]
typo3/sysext/core/Classes/Http/RequestHandlerInterface.php [new file with mode: 0644]
typo3/sysext/core/Classes/Http/ServerRequestFactory.php
typo3/sysext/frontend/Classes/Http/Application.php
typo3/sysext/frontend/Classes/Http/EidRequestHandler.php
typo3/sysext/frontend/Classes/Http/RequestHandler.php
typo3/sysext/install/Classes/Http/Application.php
typo3/sysext/install/Classes/Http/RequestHandler.php

index bca462e..26868fb 100644 (file)
@@ -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) {
index 3e9c24f..6b61195 100644 (file)
@@ -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);
        }
 
index 306d7d2..554ad8f 100644 (file)
@@ -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;
 
index 01ebd90..b860541 100644 (file)
@@ -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) {
index e31d852..de25671 100644 (file)
@@ -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
index 489616e..2860c42 100644 (file)
@@ -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 (file)
index 0000000..32cf549
--- /dev/null
@@ -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();
+
+}
index 616878b..8c88d91 100644 (file)
@@ -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/Core/RequestHandlerInterface.php
deleted file mode 100644 (file)
index 7af6f42..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\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!
- */
-
-/**
- * The interface for a request handler
- * see RequestHandler in EXT:backend/Classes/Http/ and EXT:frontend/Classes/Http
- *
- * @api
- */
-interface RequestHandlerInterface {
-
-       /**
-        * Handles a raw request
-        *
-        * @param \Psr\Http\Message\ServerRequestInterface $request
-        * @return NULL|\Psr\Http\Message\ResponseInterface
-        * @api
-        */
-       public function handleRequest(\Psr\Http\Message\ServerRequestInterface $request);
-
-       /**
-        * Checks if the request handler can handle the given request.
-        *
-        * @param \Psr\Http\Message\ServerRequestInterface $request
-        * @return bool TRUE if it can handle the request, otherwise FALSE
-        * @api
-        */
-       public function canHandleRequest(\Psr\Http\Message\ServerRequestInterface $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/Http/RequestHandlerInterface.php b/typo3/sysext/core/Classes/Http/RequestHandlerInterface.php
new file mode 100644 (file)
index 0000000..33c66b6
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+namespace TYPO3\CMS\Core\Http;
+
+/*
+ * 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!
+ */
+
+/**
+ * The interface for a request handler
+ * see RequestHandler in EXT:backend/Classes/Http/ and EXT:frontend/Classes/Http
+ *
+ * @api
+ */
+interface RequestHandlerInterface {
+
+       /**
+        * Handles a raw request
+        *
+        * @param \Psr\Http\Message\ServerRequestInterface $request
+        * @return NULL|\Psr\Http\Message\ResponseInterface
+        * @api
+        */
+       public function handleRequest(\Psr\Http\Message\ServerRequestInterface $request);
+
+       /**
+        * Checks if the request handler can handle the given request.
+        *
+        * @param \Psr\Http\Message\ServerRequestInterface $request
+        * @return bool TRUE if it can handle the request, otherwise FALSE
+        * @api
+        */
+       public function canHandleRequest(\Psr\Http\Message\ServerRequestInterface $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();
+
+}
index 73014f1..85b5aec 100644 (file)
@@ -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
index 8c3f3d0..4ca07a8 100644 (file)
@@ -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) {
index 81cb6fb..09dcbc6 100644 (file)
@@ -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;
 
 /**
index b223440..9ecf498 100644 (file)
@@ -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;
index 4a44a26..bd85360 100644 (file)
@@ -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) {
index 6ccce1e..3eae52f 100644 (file)
@@ -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;
 
 /**