Skip to content

Commit 0fca61e

Browse files
authored
Merge pull request #20 from jdreesen/fix-19
Allow short-circuiting the controller in a before middleware
2 parents 4f98216 + af3ff2e commit 0fca61e

File tree

3 files changed

+66
-20
lines changed

3 files changed

+66
-20
lines changed

src/Application.php

+2-14
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44

55
use DI\Bridge\Silex\Container\ContainerInteropProxy;
66
use DI\Bridge\Silex\Controller\ControllerResolver;
7-
use DI\Bridge\Silex\MiddlewareListener;
8-
use DI\Bridge\Silex\ConverterListener;
97
use Silex\EventListener\LocaleListener;
108
use Silex\EventListener\StringToResponseListener;
119
use Silex\LazyUrlMatcher;
10+
use Symfony\Component\HttpFoundation\Response;
1211
use Symfony\Component\HttpKernel\Kernel;
1312
use Symfony\Component\HttpKernel\HttpKernelInterface;
1413
use Symfony\Component\HttpKernel\KernelEvents;
@@ -21,7 +20,6 @@
2120
use DI\ContainerBuilder;
2221
use Interop\Container\ContainerInterface;
2322
use Invoker\CallableResolver;
24-
use Invoker\Reflection\CallableReflection;
2523
use Invoker\ParameterResolver\AssociativeArrayResolver;
2624
use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
2725
use Invoker\ParameterResolver\ResolverChain;
@@ -168,7 +166,6 @@ public function before($callback, $priority = 0)
168166
if ($ret instanceof Response) {
169167
$event->setResponse($ret);
170168
}
171-
172169
}, $priority);
173170
}
174171

@@ -197,18 +194,16 @@ public function after($callback, $priority = 0)
197194
} elseif (null !== $ret) {
198195
throw new \RuntimeException('An after middleware returned an invalid response value. Must return null or an instance of Response.');
199196
}
200-
201197
}, $priority);
202198
}
203199

204200
public function finish($callback, $priority = 0)
205201
{
206202
$this->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($callback) {
207-
208203
$request = $event->getRequest();
209204
$response = $event->getResponse();
210205
$middleware = $this['callback_resolver']->resolveCallback($callback);
211-
$ret = $this->callbackInvoker->call($middleware, [
206+
$this->callbackInvoker->call($middleware, [
212207
// type hints
213208
'Symfony\Component\HttpFoundation\Request' => $request,
214209
'Symfony\Component\HttpFoundation\Response' => $response,
@@ -217,13 +212,6 @@ public function finish($callback, $priority = 0)
217212
1 => $response,
218213
2 => $this,
219214
]);
220-
221-
if ($ret instanceof Response) {
222-
$event->setResponse($ret);
223-
} elseif (null !== $ret) {
224-
throw new \RuntimeException('An after middleware returned an invalid response value. Must return null or an instance of Response.');
225-
}
226-
227215
}, $priority);
228216
}
229217
}

src/MiddlewareListener.php

+5-6
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
namespace DI\Bridge\Silex;
44

5-
use DI\Bridge\Silex\Application;
6-
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
7-
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
85
use Symfony\Component\HttpFoundation\Response;
6+
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
7+
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
98

109
/**
1110
* Replacement for the Silex MiddlewareListener to allow arbitrary injection into middleware functions.
@@ -21,7 +20,7 @@ class MiddlewareListener extends \Silex\EventListener\MiddlewareListener
2120

2221
/**
2322
* @param Application $app The application
24-
* @param CallbackInvoker $callbackInvoker The invoker that handles injecting middlewares
23+
* @param CallbackInvoker $callbackInvoker The invoker that handles injecting middleware
2524
*/
2625
public function __construct(Application $app, CallbackInvoker $callbackInvoker)
2726
{
@@ -38,7 +37,6 @@ public function onKernelRequest(GetResponseEvent $event)
3837
}
3938

4039
foreach ((array) $route->getOption('_before_middlewares') as $callback) {
41-
4240
$middleware = $this->app['callback_resolver']->resolveCallback($callback);
4341
$ret = $this->callbackInvoker->call($middleware, [
4442
// type hints
@@ -50,6 +48,8 @@ public function onKernelRequest(GetResponseEvent $event)
5048

5149
if ($ret instanceof Response) {
5250
$event->setResponse($ret);
51+
52+
return;
5353
} elseif (null !== $ret) {
5454
throw new \RuntimeException(sprintf('A before middleware for route "%s" returned an invalid response value. Must return null or an instance of Response.', $routeName));
5555
}
@@ -66,7 +66,6 @@ public function onKernelResponse(FilterResponseEvent $event)
6666
}
6767

6868
foreach ((array) $route->getOption('_after_middlewares') as $callback) {
69-
7069
$middleware = $this->app['callback_resolver']->resolveCallback($callback);
7170
$ret = $this->callbackInvoker->call($middleware, [
7271
// type hints

tests/MiddlewareTest.php

+59
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,63 @@ public function should_fall_back_to_silex_default_behaviour()
9999
$response = $application->handle($request);
100100
$this->assertEquals('Hello john', $response->getContent());
101101
}
102+
103+
/**
104+
* @test
105+
*/
106+
public function should_allow_short_circuiting_the_controller_in_before_application_middleware()
107+
{
108+
$application = $this->createApplication();
109+
$request = Request::create('/');
110+
111+
$shouldBeCalled = $this->createSpyCallback();
112+
$shouldBeCalled->expects($this->once())->method('__invoke');
113+
114+
$shouldNotBeCalled = $this->createSpyCallback();
115+
$shouldNotBeCalled->expects($this->never())->method('__invoke');
116+
117+
$application->get('/', $shouldNotBeCalled);
118+
119+
// application middleware
120+
$application->before(function () {
121+
return new Response('Expected result');
122+
});
123+
$application->before($shouldNotBeCalled);
124+
$application->after($shouldBeCalled);
125+
$application->finish($shouldBeCalled);
126+
127+
$response = $application->handle($request);
128+
$this->assertEquals('Expected result', $response->getContent());
129+
}
130+
131+
/**
132+
* @test
133+
*/
134+
public function should_allow_short_circuiting_the_controller_in_before_route_middleware()
135+
{
136+
$application = $this->createApplication();
137+
$request = Request::create('/');
138+
139+
$shouldBeCalled = $this->createSpyCallback();
140+
$shouldBeCalled->expects($this->once())->method('__invoke');
141+
142+
$shouldNotBeCalled = $this->createSpyCallback();
143+
$shouldNotBeCalled->expects($this->never())->method('__invoke');
144+
145+
// route middleware
146+
$application
147+
->get('/', $shouldNotBeCalled)
148+
->before(function () {
149+
return new Response('Expected result');
150+
})
151+
->before($shouldNotBeCalled)
152+
->after($shouldBeCalled);
153+
154+
$response = $application->handle($request);
155+
$this->assertEquals('Expected result', $response->getContent());
156+
}
157+
158+
private function createSpyCallback() {
159+
return $this->getMockBuilder('stdClass')->setMethods(['__invoke'])->getMock();
160+
}
102161
}

0 commit comments

Comments
 (0)