Skip to content

Commit

Permalink
Merge pull request #17 from jdreesen/silex-2
Browse files Browse the repository at this point in the history
Compatibility with Silex 2
  • Loading branch information
mnapoli committed Jun 2, 2016
2 parents 84306c3 + b6982ff commit d0e8987
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 73 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"php": ">=5.5.9",
"php-di/php-di": "~5.0",
"php-di/invoker": "~1.3",
"silex/silex" : "~2.0@dev",
"silex/silex" : "~2.0",
"pimple/pimple" : "~3.0"
},
"require-dev": {
Expand Down
83 changes: 11 additions & 72 deletions src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,16 @@
namespace DI\Bridge\Silex;

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\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\EventListener\ResponseListener;
use Symfony\Component\HttpKernel\EventListener\RouterListener;
use DI\Bridge\Silex\Provider\HttpKernelServiceProvider;
use DI\Container;
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;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
* Replacement for the Silex Application class to use PHP-DI instead of Pimple.
Expand Down Expand Up @@ -72,51 +60,8 @@ public function __construct(ContainerBuilder $containerBuilder = null, array $va
return new CallableResolver($this->containerInteropProxy);
};

// Override the controller resolver with ours
$this['resolver'] = function () {
return new ControllerResolver(
$this['phpdi.callable_resolver'],
new ResolverChain([
new AssociativeArrayResolver,
new TypeHintContainerResolver($this->containerInteropProxy),
])
);
};

// Override the callback resolver with ours
$this['callback_resolver'] = function () {
return new CallbackResolver(
$this,
$this['phpdi.callable_resolver']
);
};

// Override the dispatcher with ours to use our event listeners
$this['dispatcher'] = $this->share(function () {
/**
* @var EventDispatcherInterface
*/
$dispatcher = new $this['dispatcher_class']();

$urlMatcher = new LazyUrlMatcher(function () {
return $this['url_matcher'];
});
if (Kernel::VERSION_ID >= 20800) {
$dispatcher->addSubscriber(new RouterListener($urlMatcher, $this['request_stack'], $this['request_context'], $this['logger']));
} else {
$dispatcher->addSubscriber(new RouterListener($urlMatcher, $this['request_context'], $this['logger'], $this['request_stack']));
}
$dispatcher->addSubscriber(new LocaleListener($this, $urlMatcher, $this['request_stack']));
if (isset($this['exception_handler'])) {
$dispatcher->addSubscriber($this['exception_handler']);
}
$dispatcher->addSubscriber(new ResponseListener($this['charset']));
$dispatcher->addSubscriber(new MiddlewareListener($this, $this->callbackInvoker));
$dispatcher->addSubscriber(new ConverterListener($this['routes'], $this['callback_resolver'], $this->callbackInvoker));
$dispatcher->addSubscriber(new StringToResponseListener());

return $dispatcher;
});
// Register own HttpKernelServiceProvider which overrides some defaults.
$this->register(new HttpKernelServiceProvider($this->containerInteropProxy, $this->callbackInvoker));
}

public function offsetGet($id)
Expand Down Expand Up @@ -151,7 +96,7 @@ public function getPhpDi()
public function before($callback, $priority = 0)
{
$this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($callback) {
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
if (!$event->isMasterRequest()) {
return;
}

Expand All @@ -175,7 +120,7 @@ public function before($callback, $priority = 0)
public function after($callback, $priority = 0)
{
$this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($callback) {
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
if (!$event->isMasterRequest()) {
return;
}

Expand Down Expand Up @@ -208,7 +153,7 @@ public function finish($callback, $priority = 0)
$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 @@ -218,12 +163,6 @@ public function finish($callback, $priority = 0)
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);
}
}
98 changes: 98 additions & 0 deletions src/Provider/HttpKernelServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

namespace DI\Bridge\Silex\Provider;

use DI\Bridge\Silex\CallbackInvoker;
use DI\Bridge\Silex\CallbackResolver;
use DI\Bridge\Silex\Controller\ControllerResolver;
use DI\Bridge\Silex\ConverterListener;
use DI\Bridge\Silex\MiddlewareListener;
use Interop\Container\ContainerInterface;
use Invoker\ParameterResolver\AssociativeArrayResolver;
use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
use Invoker\ParameterResolver\ResolverChain;
use Pimple\ServiceProviderInterface;
use Silex\Api\EventListenerProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* @author Jacob Dreesen <jacob.dreesen@gmail.com>
*/
class HttpKernelServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
{
/**
* @var ContainerInterface
*/
private $container;

/**
* @var CallbackInvoker
*/
private $callbackInvoker;

/**
* @param ContainerInterface $container
* @param CallbackInvoker $callbackInvoker
*/
public function __construct(ContainerInterface $container, CallbackInvoker $callbackInvoker)
{
$this->container = $container;
$this->callbackInvoker = $callbackInvoker;
}

public function register(\Pimple\Container $app)
{
// Override the controller resolver with ours.
$app['resolver'] = function ($app) {
return new ControllerResolver(
$app['phpdi.callable_resolver'],
new ResolverChain([
new AssociativeArrayResolver,
new TypeHintContainerResolver($this->container),
])
);
};

// Override the callback resolver with ours.
$app['callback_resolver'] = function ($app) {
return new CallbackResolver(
$app,
$app['phpdi.callable_resolver']
);
};
}

public function subscribe(\Pimple\Container $app, EventDispatcherInterface $dispatcher)
{
// Remove the Silex listeners first
$this->removeSubscriber($dispatcher, \Silex\EventListener\MiddlewareListener::class);
$this->removeSubscriber($dispatcher, \Silex\EventListener\ConverterListener::class);

// And register ours instead
$dispatcher->addSubscriber(new MiddlewareListener($app, $this->callbackInvoker));
$dispatcher->addSubscriber(new ConverterListener($app['routes'], $app['callback_resolver'], $this->callbackInvoker));
}

/**
* Removes an event subscriber by its class name.
*
* @param EventDispatcherInterface $dispatcher
* @param string $subscriberClass
*/
private function removeSubscriber(EventDispatcherInterface $dispatcher, $subscriberClass)
{
if (!is_subclass_of($subscriberClass, EventSubscriberInterface::class, true)) {
throw new \InvalidArgumentException('$subscriberClass must implement ' . EventSubscriberInterface::class);
}

/** @var EventSubscriberInterface $subscriberClass */
foreach ($subscriberClass::getSubscribedEvents() as $eventName => $params) {
foreach ($dispatcher->getListeners($eventName) as $listener) {
if (is_array($listener) && is_a($listener[0], $subscriberClass, true)) {
$dispatcher->removeListener($eventName, $listener);
}
}
}
}
}
1 change: 1 addition & 0 deletions tests/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public function the_callback_resolver_should_be_registered_as_a_service()
{
$app = new Application();

$this->assertInstanceOf('Closure', $app->raw('callback_resolver'));
$this->assertInstanceOf('DI\Bridge\Silex\CallbackResolver', $app['callback_resolver']);
}
}

0 comments on commit d0e8987

Please sign in to comment.