Skip to content

Commit

Permalink
Merge pull request #20 from jdreesen/fix-19
Browse files Browse the repository at this point in the history
Allow short-circuiting the controller in a before middleware
  • Loading branch information
jdreesen authored Jun 10, 2016
2 parents 4f98216 + af3ff2e commit 0fca61e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 20 deletions.
16 changes: 2 additions & 14 deletions src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

use DI\Bridge\Silex\Container\ContainerInteropProxy;
use DI\Bridge\Silex\Controller\ControllerResolver;
use DI\Bridge\Silex\MiddlewareListener;
use DI\Bridge\Silex\ConverterListener;
use Silex\EventListener\LocaleListener;
use Silex\EventListener\StringToResponseListener;
use Silex\LazyUrlMatcher;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
Expand All @@ -21,7 +20,6 @@
use DI\ContainerBuilder;
use Interop\Container\ContainerInterface;
use Invoker\CallableResolver;
use Invoker\Reflection\CallableReflection;
use Invoker\ParameterResolver\AssociativeArrayResolver;
use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
use Invoker\ParameterResolver\ResolverChain;
Expand Down Expand Up @@ -168,7 +166,6 @@ public function before($callback, $priority = 0)
if ($ret instanceof Response) {
$event->setResponse($ret);
}

}, $priority);
}

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

}, $priority);
}

public function finish($callback, $priority = 0)
{
$this->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($callback) {

$request = $event->getRequest();
$response = $event->getResponse();
$middleware = $this['callback_resolver']->resolveCallback($callback);
$ret = $this->callbackInvoker->call($middleware, [
$this->callbackInvoker->call($middleware, [
// type hints
'Symfony\Component\HttpFoundation\Request' => $request,
'Symfony\Component\HttpFoundation\Response' => $response,
Expand All @@ -217,13 +212,6 @@ public function finish($callback, $priority = 0)
1 => $response,
2 => $this,
]);

if ($ret instanceof Response) {
$event->setResponse($ret);
} elseif (null !== $ret) {
throw new \RuntimeException('An after middleware returned an invalid response value. Must return null or an instance of Response.');
}

}, $priority);
}
}
11 changes: 5 additions & 6 deletions src/MiddlewareListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

namespace DI\Bridge\Silex;

use DI\Bridge\Silex\Application;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

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

/**
* @param Application $app The application
* @param CallbackInvoker $callbackInvoker The invoker that handles injecting middlewares
* @param CallbackInvoker $callbackInvoker The invoker that handles injecting middleware
*/
public function __construct(Application $app, CallbackInvoker $callbackInvoker)
{
Expand All @@ -38,7 +37,6 @@ public function onKernelRequest(GetResponseEvent $event)
}

foreach ((array) $route->getOption('_before_middlewares') as $callback) {

$middleware = $this->app['callback_resolver']->resolveCallback($callback);
$ret = $this->callbackInvoker->call($middleware, [
// type hints
Expand All @@ -50,6 +48,8 @@ public function onKernelRequest(GetResponseEvent $event)

if ($ret instanceof Response) {
$event->setResponse($ret);

return;
} elseif (null !== $ret) {
throw new \RuntimeException(sprintf('A before middleware for route "%s" returned an invalid response value. Must return null or an instance of Response.', $routeName));
}
Expand All @@ -66,7 +66,6 @@ public function onKernelResponse(FilterResponseEvent $event)
}

foreach ((array) $route->getOption('_after_middlewares') as $callback) {

$middleware = $this->app['callback_resolver']->resolveCallback($callback);
$ret = $this->callbackInvoker->call($middleware, [
// type hints
Expand Down
59 changes: 59 additions & 0 deletions tests/MiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,63 @@ public function should_fall_back_to_silex_default_behaviour()
$response = $application->handle($request);
$this->assertEquals('Hello john', $response->getContent());
}

/**
* @test
*/
public function should_allow_short_circuiting_the_controller_in_before_application_middleware()
{
$application = $this->createApplication();
$request = Request::create('/');

$shouldBeCalled = $this->createSpyCallback();
$shouldBeCalled->expects($this->once())->method('__invoke');

$shouldNotBeCalled = $this->createSpyCallback();
$shouldNotBeCalled->expects($this->never())->method('__invoke');

$application->get('/', $shouldNotBeCalled);

// application middleware
$application->before(function () {
return new Response('Expected result');
});
$application->before($shouldNotBeCalled);
$application->after($shouldBeCalled);
$application->finish($shouldBeCalled);

$response = $application->handle($request);
$this->assertEquals('Expected result', $response->getContent());
}

/**
* @test
*/
public function should_allow_short_circuiting_the_controller_in_before_route_middleware()
{
$application = $this->createApplication();
$request = Request::create('/');

$shouldBeCalled = $this->createSpyCallback();
$shouldBeCalled->expects($this->once())->method('__invoke');

$shouldNotBeCalled = $this->createSpyCallback();
$shouldNotBeCalled->expects($this->never())->method('__invoke');

// route middleware
$application
->get('/', $shouldNotBeCalled)
->before(function () {
return new Response('Expected result');
})
->before($shouldNotBeCalled)
->after($shouldBeCalled);

$response = $application->handle($request);
$this->assertEquals('Expected result', $response->getContent());
}

private function createSpyCallback() {
return $this->getMockBuilder('stdClass')->setMethods(['__invoke'])->getMock();
}
}

0 comments on commit 0fca61e

Please sign in to comment.