From 7bcb180f27972e3e80fb97c39dc00d2f6dfb3682 Mon Sep 17 00:00:00 2001 From: Marcus Nyeholt Date: Tue, 15 Oct 2013 07:53:34 +1100 Subject: [PATCH] BUG Director::test now calls RequestProcessor This fixes https://github.com/silverstripe/silverstripe-framework/issues/2517 and provides some testing around the use of RequestProcessor in general. --- control/Director.php | 17 ++++++++- control/injector/Injector.php | 9 ++--- tests/control/DirectorTest.php | 66 ++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 5 deletions(-) diff --git a/control/Director.php b/control/Director.php index a8cb375bf..afb3335d5 100644 --- a/control/Director.php +++ b/control/Director.php @@ -258,8 +258,18 @@ class Director implements TemplateGlobalProvider { $request = new SS_HTTPRequest($httpMethod, $url, $getVars, $postVars, $body); if($headers) foreach($headers as $k => $v) $request->addHeader($k, $v); + + // Pre-request filtering + // @see issue #2517 + $model = DataModel::inst(); + $output = Injector::inst()->get('RequestProcessor')->preRequest($request, $session, $model); + if ($output === false) { + // @TODO Need to NOT proceed with the request in an elegant manner + throw new SS_HTTPResponse_Exception(_t('Director.INVALID_REQUEST', 'Invalid request'), 400); + } + // TODO: Pass in the DataModel - $result = Director::handleRequest($request, $session, DataModel::inst()); + $result = Director::handleRequest($request, $session, $model); // Ensure that the result is an SS_HTTPResponse object if(is_string($result)) { @@ -272,6 +282,11 @@ class Director implements TemplateGlobalProvider { } } + $output = Injector::inst()->get('RequestProcessor')->postRequest($request, $result, $model); + if ($output === false) { + throw new SS_HTTPResponse_Exception("Invalid response"); + } + // Restore the superglobals $_REQUEST = $existingRequestVars; $_GET = $existingGetVars; diff --git a/control/injector/Injector.php b/control/injector/Injector.php index 3c6cc7f0c..82d9cae6f 100644 --- a/control/injector/Injector.php +++ b/control/injector/Injector.php @@ -683,23 +683,24 @@ class Injector { * class name of the object to register) * */ - public function registerService($service, $replace=null) { + public function registerService($service, $replace = null) { $registerAt = get_class($service); if ($replace != null) { $registerAt = $replace; } + $this->specs[$registerAt] = array('class' => get_class($service)); $this->serviceCache[$registerAt] = $service; $this->inject($service); } /** * Register a service with an explicit name + * + * @deprecated since 3.1.1 */ public function registerNamedService($name, $service) { - $this->specs[$name] = array('class' => get_class($service)); - $this->serviceCache[$name] = $service; - $this->inject($service); + return $this->registerService($service, $name); } /** diff --git a/tests/control/DirectorTest.php b/tests/control/DirectorTest.php index 9568307e5..adbaeae6e 100644 --- a/tests/control/DirectorTest.php +++ b/tests/control/DirectorTest.php @@ -344,6 +344,72 @@ class DirectorTest extends SapphireTest { $_SERVER = $origServer; } + + public function testRequestFilterInDirectorTest() { + $filter = new TestRequestFilter; + + $processor = new RequestProcessor(array($filter)); + + $currentProcessor = Injector::inst()->get('RequestProcessor'); + + Injector::inst()->registerService($processor, 'RequestProcessor'); + + $response = Director::test('some-dummy-url'); + + $this->assertEquals(1, $filter->preCalls); + $this->assertEquals(1, $filter->postCalls); + + $filter->failPost = true; + + $this->setExpectedException('SS_HTTPResponse_Exception'); + + $response = Director::test('some-dummy-url'); + + $this->assertEquals(2, $filter->preCalls); + $this->assertEquals(2, $filter->postCalls); + + $filter->failPre = true; + + $response = Director::test('some-dummy-url'); + + $this->assertEquals(3, $filter->preCalls); + + // preCall 'false' will trigger an exception and prevent post call execution + $this->assertEquals(2, $filter->postCalls); + + // swap back otherwise our wrapping test execution request may fail in the post processing later + Injector::inst()->registerService($currentProcessor, 'RequestProcessor'); + } +} + +class TestRequestFilter implements RequestFilter, TestOnly { + public $preCalls = 0; + public $postCalls = 0; + + public $failPre = false; + public $failPost = false; + + public function preRequest(\SS_HTTPRequest $request, \Session $session, \DataModel $model) { + ++$this->preCalls; + + if ($this->failPre) { + return false; + } + } + + public function postRequest(\SS_HTTPRequest $request, \SS_HTTPResponse $response, \DataModel $model) { + ++$this->postCalls; + + if ($this->failPost) { + return false; + } + } + + public function reset() { + $this->preCalls = 0; + $this->postCalls = 0; + } + } class DirectorTestRequest_Controller extends Controller implements TestOnly {