-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from felixfbecker/master
Allow arbitrary injection into middleware and param converters
- Loading branch information
Showing
8 changed files
with
498 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
namespace DI\Bridge\Silex; | ||
|
||
use DI\Bridge\Silex\Application; | ||
use Invoker\Invoker; | ||
use Interop\Container\ContainerInterface; | ||
use Invoker\ParameterResolver\ResolverChain; | ||
use Invoker\ParameterResolver\TypeHintResolver; | ||
use Invoker\ParameterResolver\AssociativeArrayResolver; | ||
use Invoker\ParameterResolver\Container\TypeHintContainerResolver; | ||
use Invoker\ParameterResolver\NumericArrayResolver; | ||
|
||
/** | ||
* A subclass of Invoker that always tries to first resolve through provided parameter names, then | ||
* type hints, then through the DI container and finally allows a fallback to a default parameter order | ||
* | ||
* @author Felix Becker <[email protected]> | ||
*/ | ||
class CallbackInvoker extends Invoker | ||
{ | ||
/** | ||
* @param ContainerInterface $container the container for injection | ||
*/ | ||
public function __construct(ContainerInterface $container) | ||
{ | ||
parent::__construct(new ResolverChain([ | ||
new AssociativeArrayResolver, | ||
new TypeHintResolver, | ||
new TypeHintContainerResolver($container), | ||
new NumericArrayResolver, | ||
])); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?php | ||
|
||
namespace DI\Bridge\Silex; | ||
|
||
use DI\Bridge\Silex\CallbackResolver; | ||
use Interop\Container\ContainerInterface; | ||
use Symfony\Component\HttpKernel\Event\FilterControllerEvent; | ||
use Symfony\Component\Routing\RouteCollection; | ||
|
||
/** | ||
* Replacement for the Silex ConverterListener to allow arbitrary injection into param converters. | ||
* | ||
* @author Felix Becker <[email protected]> | ||
*/ | ||
class ConverterListener extends \Silex\EventListener\ConverterListener | ||
{ | ||
/** | ||
* @var CallbackInvoker | ||
*/ | ||
private $callbackInvoker; | ||
|
||
/** | ||
* @param RouteCollection $routes A RouteCollection instance | ||
* @param CallbackResolver $callbackResolver A CallbackResolver instance | ||
* @param CallbackInvoker $callbackInvoker The invoker that handles resolving and injecting param converters | ||
*/ | ||
public function __construct(RouteCollection $routes, CallbackResolver $callbackResolver, CallbackInvoker $callbackInvoker) | ||
{ | ||
parent::__construct($routes, $callbackResolver); | ||
$this->callbackInvoker = $callbackInvoker; | ||
} | ||
|
||
public function onKernelController(FilterControllerEvent $event) | ||
{ | ||
$request = $event->getRequest(); | ||
$route = $this->routes->get($request->attributes->get('_route')); | ||
if ($route && $converters = $route->getOption('_converters')) { | ||
foreach ($converters as $name => $callback) { | ||
|
||
$value = $request->attributes->get($name); | ||
$middleware = $this->callbackResolver->resolveCallback($callback); | ||
$ret = $this->callbackInvoker->call($middleware, [ | ||
// parameter name | ||
$name => $value, | ||
// type hints | ||
'Symfony\Component\HttpFoundation\Request' => $request, | ||
// Silex' default parameter order | ||
0 => $value, | ||
1 => $request, | ||
]); | ||
|
||
$request->attributes->set($name, $ret); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<?php | ||
|
||
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; | ||
|
||
/** | ||
* Replacement for the Silex MiddlewareListener to allow arbitrary injection into middleware functions. | ||
* | ||
* @author Felix Becker <[email protected]> | ||
*/ | ||
class MiddlewareListener extends \Silex\EventListener\MiddlewareListener | ||
{ | ||
/** | ||
* @var CallbackInvoker | ||
*/ | ||
private $callbackInvoker; | ||
|
||
/** | ||
* @param Application $app The application | ||
* @param CallbackInvoker $callbackInvoker The invoker that handles injecting middlewares | ||
*/ | ||
public function __construct(Application $app, CallbackInvoker $callbackInvoker) | ||
{ | ||
parent::__construct($app); | ||
$this->callbackInvoker = $callbackInvoker; | ||
} | ||
|
||
public function onKernelRequest(GetResponseEvent $event) | ||
{ | ||
$request = $event->getRequest(); | ||
$routeName = $request->attributes->get('_route'); | ||
if (!$route = $this->app['routes']->get($routeName)) { | ||
return; | ||
} | ||
|
||
foreach ((array) $route->getOption('_before_middlewares') as $callback) { | ||
|
||
$middleware = $this->app['callback_resolver']->resolveCallback($callback); | ||
$ret = $this->callbackInvoker->call($middleware, [ | ||
// type hints | ||
'Symfony\Component\HttpFoundation\Request' => $request, | ||
// Silex' default parameter order | ||
0 => $request, | ||
1 => $this->app, | ||
]); | ||
|
||
if ($ret instanceof Response) { | ||
$event->setResponse($ret); | ||
} 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)); | ||
} | ||
} | ||
} | ||
|
||
public function onKernelResponse(FilterResponseEvent $event) | ||
{ | ||
$request = $event->getRequest(); | ||
$response = $event->getResponse(); | ||
$routeName = $request->attributes->get('_route'); | ||
if (!$route = $this->app['routes']->get($routeName)) { | ||
return; | ||
} | ||
|
||
foreach ((array) $route->getOption('_after_middlewares') as $callback) { | ||
|
||
$middleware = $this->app['callback_resolver']->resolveCallback($callback); | ||
$ret = $this->callbackInvoker->call($middleware, [ | ||
// type hints | ||
'Symfony\Component\HttpFoundation\Request' => $request, | ||
'Symfony\Component\HttpFoundation\Response' => $response, | ||
// Silex' default parameter order | ||
0 => $request, | ||
1 => $response, | ||
2 => $this->app, | ||
]); | ||
|
||
if ($ret instanceof Response) { | ||
$event->setResponse($ret); | ||
} elseif (null !== $ret) { | ||
throw new \RuntimeException(sprintf('An after middleware for route "%s" returned an invalid response value. Must return null or an instance of Response.', $routeName)); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.