diff --git a/main.php b/main.php index f8696d9da..9d14f8981 100644 --- a/main.php +++ b/main.php @@ -15,5 +15,5 @@ $request = HTTPRequest::createFromEnvironment(); $kernel = new AppKernel(); $app = new HTTPApplication($kernel); $app->addMiddleware(new OutputMiddleware()); -$app->addMiddleware(new ErrorControlChainMiddleware($app, $request)); +$app->addMiddleware(new ErrorControlChainMiddleware($app)); $app->handle($request); diff --git a/src/Control/HTTPRequest.php b/src/Control/HTTPRequest.php index e1e0debc4..c28dd3db8 100644 --- a/src/Control/HTTPRequest.php +++ b/src/Control/HTTPRequest.php @@ -316,7 +316,7 @@ class HTTPRequest implements ArrayAccess } // Initiate an empty session - doesn't initialize an actual PHP session (see HTTPApplication) - $session = new Session($variables['_SESSION']); + $session = new Session(isset($variables['_SESSION']) ? $variables['_SESSION'] : null); $request->setSession($session); return $request; diff --git a/src/Core/Application.php b/src/Core/Application.php index deb0d60aa..fe4fbcabd 100644 --- a/src/Core/Application.php +++ b/src/Core/Application.php @@ -13,13 +13,4 @@ interface Application * @return Kernel */ public function getKernel(); - - /** - * Invoke the application control chain - * - * @param callable $callback - * @param bool $flush - * @return mixed - */ - public function execute(callable $callback, $flush = false); } diff --git a/src/Core/HTTPApplication.php b/src/Core/HTTPApplication.php index 1a64106c6..73eba9061 100644 --- a/src/Core/HTTPApplication.php +++ b/src/Core/HTTPApplication.php @@ -12,12 +12,12 @@ use SilverStripe\Control\HTTPResponse; class HTTPApplication implements Application { /** - * @var callable[] + * @var HTTPMiddleware[] */ protected $middlewares = []; /** - * @return callable[] + * @return HTTPMiddleware[] */ public function getMiddlewares() { @@ -25,7 +25,7 @@ class HTTPApplication implements Application } /** - * @param callable[] $middlewares + * @param HTTPMiddleware[] $middlewares * @return $this */ public function setMiddlewares($middlewares) @@ -35,10 +35,10 @@ class HTTPApplication implements Application } /** - * @param callable $middleware + * @param HTTPMiddleware $middleware * @return $this */ - public function addMiddleware($middleware) + public function addMiddleware(HTTPMiddleware $middleware) { $this->middlewares[] = $middleware; return $this; @@ -47,19 +47,21 @@ class HTTPApplication implements Application /** * Call middleware * + * @param HTTPRequest $request * @param callable $last Last config to call * @return HTTPResponse */ - protected function callMiddleware($last) + protected function callMiddleware(HTTPRequest $request, $last) { // Reverse middlewares $next = $last; + /** @var HTTPMiddleware $middleware */ foreach (array_reverse($this->getMiddlewares()) as $middleware) { - $next = function () use ($middleware, $next) { - return call_user_func($middleware, $next); + $next = function ($request) use ($middleware, $next) { + return $middleware->process($request, $next); }; } - return call_user_func($next); + return call_user_func($next, $request); } /** @@ -93,7 +95,7 @@ class HTTPApplication implements Application $flush = $request->getVar('flush') || strpos($request->getURL(), 'dev/build') === 0; // Ensure boot is invoked - return $this->execute(function () use ($request) { + return $this->execute($request, function (HTTPRequest $request) { // Start session and execute $request->getSession()->init(); return Director::direct($request); @@ -103,17 +105,18 @@ class HTTPApplication implements Application /** * Safely boot the application and execute the given main action * + * @param HTTPRequest $request * @param callable $callback * @param bool $flush * @return HTTPResponse */ - public function execute(callable $callback, $flush = false) + public function execute(HTTPRequest $request, callable $callback, $flush = false) { try { - return $this->callMiddleware(function () use ($callback, $flush) { + return $this->callMiddleware($request, function ($request) use ($callback, $flush) { // Pre-request boot $this->getKernel()->boot($flush); - return call_user_func($callback); + return call_user_func($callback, $request); }); } finally { $this->getKernel()->shutdown(); diff --git a/src/Core/HTTPMiddleware.php b/src/Core/HTTPMiddleware.php new file mode 100644 index 000000000..8d5dc60da --- /dev/null +++ b/src/Core/HTTPMiddleware.php @@ -0,0 +1,22 @@ +application = $application; - $this->request = $request; } - /** - * @param callable $next - * @return HTTPResponse - */ - public function __invoke(callable $next) + public function process(HTTPRequest $request, callable $next) { $result = null; // Prepare tokens and execute chain $reloadToken = ParameterConfirmationToken::prepare_tokens( ['isTest', 'isDev', 'flush'], - $this->getRequest() + $request ); $chain = new ErrorControlChain(); $chain - ->then(function () use ($chain, $reloadToken, $next, &$result) { + ->then(function () use ($request, $chain, $reloadToken, $next, &$result) { // If no redirection is necessary then we can disable error supression if (!$reloadToken) { $chain->setSuppression(false); @@ -61,10 +51,10 @@ class ErrorControlChainMiddleware try { // Check if a token is requesting a redirect if ($reloadToken) { - $result = $this->safeReloadWithToken($reloadToken); + $result = $this->safeReloadWithToken($request, $reloadToken); } else { // If no reload necessary, process application - $result = call_user_func($next); + $result = call_user_func($next, $request); } } catch (HTTPResponse_Exception $exception) { $result = $exception->getResponse(); @@ -84,16 +74,17 @@ class ErrorControlChainMiddleware * Reload application with the given token, but only if either the user is authenticated, * or authentication is impossible. * + * @param HTTPRequest $request * @param ParameterConfirmationToken $reloadToken * @return HTTPResponse */ - protected function safeReloadWithToken($reloadToken) + protected function safeReloadWithToken(HTTPRequest $request, $reloadToken) { // Safe reload requires manual boot $this->getApplication()->getKernel()->boot(false); // Ensure session is started - $this->getRequest()->getSession()->init(); + $request->getSession()->init(); // Next, check if we're in dev mode, or the database doesn't have any security data, or we are admin if (Director::isDev() || !Security::database_is_ready() || Permission::check('ADMIN')) { @@ -102,7 +93,7 @@ class ErrorControlChainMiddleware // Fail and redirect the user to the login page $loginPage = Director::absoluteURL(Security::config()->get('login_url')); - $loginPage .= "?BackURL=" . urlencode($this->getRequest()->getURL()); + $loginPage .= "?BackURL=" . urlencode($request->getURL()); $result = new HTTPResponse(); $result->redirect($loginPage); return $result; @@ -125,22 +116,4 @@ class ErrorControlChainMiddleware $this->application = $application; return $this; } - - /** - * @return HTTPRequest - */ - public function getRequest() - { - return $this->request; - } - - /** - * @param HTTPRequest $request - * @return $this - */ - public function setRequest(HTTPRequest $request) - { - $this->request = $request; - return $this; - } } diff --git a/src/Core/Startup/OutputMiddleware.php b/src/Core/Startup/OutputMiddleware.php index d04a349ca..f5af2637a 100644 --- a/src/Core/Startup/OutputMiddleware.php +++ b/src/Core/Startup/OutputMiddleware.php @@ -2,13 +2,15 @@ namespace SilverStripe\Core\Startup; +use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse_Exception; +use SilverStripe\Core\HTTPMiddleware; /** * Emits response to the browser */ -class OutputMiddleware +class OutputMiddleware implements HTTPMiddleware { protected $defaultResponse = null; @@ -24,11 +26,11 @@ class OutputMiddleware $this->defaultResponse = $defaultResponse; } - public function __invoke(callable $next) + public function process(HTTPRequest $request, callable $delegate) { /** @var HTTPResponse $response */ try { - $response = call_user_func($next); + $response = call_user_func($delegate, $request); } catch (HTTPResponse_Exception $exception) { $response = $exception->getResponse(); } diff --git a/src/Dev/SapphireTest.php b/src/Dev/SapphireTest.php index 5e796fa41..6a0dd94cb 100644 --- a/src/Dev/SapphireTest.php +++ b/src/Dev/SapphireTest.php @@ -898,7 +898,7 @@ class SapphireTest extends PHPUnit_Framework_TestCase $app = new HTTPApplication($kernel); // Custom application - $app->execute(function () use ($request) { + $app->execute($request, function (HTTPRequest $request) { // Start session and execute $request->getSession()->init();