Skip to content

Commit d0e8987

Browse files
committed
Merge pull request #17 from jdreesen/silex-2
Compatibility with Silex 2
2 parents 84306c3 + b6982ff commit d0e8987

File tree

4 files changed

+111
-73
lines changed

4 files changed

+111
-73
lines changed

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"php": ">=5.5.9",
1818
"php-di/php-di": "~5.0",
1919
"php-di/invoker": "~1.3",
20-
"silex/silex" : "~2.0@dev",
20+
"silex/silex" : "~2.0",
2121
"pimple/pimple" : "~3.0"
2222
},
2323
"require-dev": {

src/Application.php

+11-72
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,16 @@
33
namespace DI\Bridge\Silex;
44

55
use DI\Bridge\Silex\Container\ContainerInteropProxy;
6-
use DI\Bridge\Silex\Controller\ControllerResolver;
7-
use DI\Bridge\Silex\MiddlewareListener;
8-
use DI\Bridge\Silex\ConverterListener;
9-
use Silex\EventListener\LocaleListener;
10-
use Silex\EventListener\StringToResponseListener;
11-
use Silex\LazyUrlMatcher;
12-
use Symfony\Component\HttpKernel\Kernel;
13-
use Symfony\Component\HttpKernel\HttpKernelInterface;
14-
use Symfony\Component\HttpKernel\KernelEvents;
15-
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
16-
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
17-
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
18-
use Symfony\Component\HttpKernel\EventListener\ResponseListener;
19-
use Symfony\Component\HttpKernel\EventListener\RouterListener;
6+
use DI\Bridge\Silex\Provider\HttpKernelServiceProvider;
207
use DI\Container;
218
use DI\ContainerBuilder;
229
use Interop\Container\ContainerInterface;
2310
use Invoker\CallableResolver;
24-
use Invoker\Reflection\CallableReflection;
25-
use Invoker\ParameterResolver\AssociativeArrayResolver;
26-
use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
27-
use Invoker\ParameterResolver\ResolverChain;
11+
use Symfony\Component\HttpFoundation\Response;
12+
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
13+
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
14+
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
15+
use Symfony\Component\HttpKernel\KernelEvents;
2816

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

75-
// Override the controller resolver with ours
76-
$this['resolver'] = function () {
77-
return new ControllerResolver(
78-
$this['phpdi.callable_resolver'],
79-
new ResolverChain([
80-
new AssociativeArrayResolver,
81-
new TypeHintContainerResolver($this->containerInteropProxy),
82-
])
83-
);
84-
};
85-
86-
// Override the callback resolver with ours
87-
$this['callback_resolver'] = function () {
88-
return new CallbackResolver(
89-
$this,
90-
$this['phpdi.callable_resolver']
91-
);
92-
};
93-
94-
// Override the dispatcher with ours to use our event listeners
95-
$this['dispatcher'] = $this->share(function () {
96-
/**
97-
* @var EventDispatcherInterface
98-
*/
99-
$dispatcher = new $this['dispatcher_class']();
100-
101-
$urlMatcher = new LazyUrlMatcher(function () {
102-
return $this['url_matcher'];
103-
});
104-
if (Kernel::VERSION_ID >= 20800) {
105-
$dispatcher->addSubscriber(new RouterListener($urlMatcher, $this['request_stack'], $this['request_context'], $this['logger']));
106-
} else {
107-
$dispatcher->addSubscriber(new RouterListener($urlMatcher, $this['request_context'], $this['logger'], $this['request_stack']));
108-
}
109-
$dispatcher->addSubscriber(new LocaleListener($this, $urlMatcher, $this['request_stack']));
110-
if (isset($this['exception_handler'])) {
111-
$dispatcher->addSubscriber($this['exception_handler']);
112-
}
113-
$dispatcher->addSubscriber(new ResponseListener($this['charset']));
114-
$dispatcher->addSubscriber(new MiddlewareListener($this, $this->callbackInvoker));
115-
$dispatcher->addSubscriber(new ConverterListener($this['routes'], $this['callback_resolver'], $this->callbackInvoker));
116-
$dispatcher->addSubscriber(new StringToResponseListener());
117-
118-
return $dispatcher;
119-
});
63+
// Register own HttpKernelServiceProvider which overrides some defaults.
64+
$this->register(new HttpKernelServiceProvider($this->containerInteropProxy, $this->callbackInvoker));
12065
}
12166

12267
public function offsetGet($id)
@@ -151,7 +96,7 @@ public function getPhpDi()
15196
public function before($callback, $priority = 0)
15297
{
15398
$this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($callback) {
154-
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
99+
if (!$event->isMasterRequest()) {
155100
return;
156101
}
157102

@@ -175,7 +120,7 @@ public function before($callback, $priority = 0)
175120
public function after($callback, $priority = 0)
176121
{
177122
$this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($callback) {
178-
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
123+
if (!$event->isMasterRequest()) {
179124
return;
180125
}
181126

@@ -208,7 +153,7 @@ public function finish($callback, $priority = 0)
208153
$request = $event->getRequest();
209154
$response = $event->getResponse();
210155
$middleware = $this['callback_resolver']->resolveCallback($callback);
211-
$ret = $this->callbackInvoker->call($middleware, [
156+
$this->callbackInvoker->call($middleware, [
212157
// type hints
213158
'Symfony\Component\HttpFoundation\Request' => $request,
214159
'Symfony\Component\HttpFoundation\Response' => $response,
@@ -218,12 +163,6 @@ public function finish($callback, $priority = 0)
218163
2 => $this,
219164
]);
220165

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-
227166
}, $priority);
228167
}
229168
}
+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
namespace DI\Bridge\Silex\Provider;
4+
5+
use DI\Bridge\Silex\CallbackInvoker;
6+
use DI\Bridge\Silex\CallbackResolver;
7+
use DI\Bridge\Silex\Controller\ControllerResolver;
8+
use DI\Bridge\Silex\ConverterListener;
9+
use DI\Bridge\Silex\MiddlewareListener;
10+
use Interop\Container\ContainerInterface;
11+
use Invoker\ParameterResolver\AssociativeArrayResolver;
12+
use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
13+
use Invoker\ParameterResolver\ResolverChain;
14+
use Pimple\ServiceProviderInterface;
15+
use Silex\Api\EventListenerProviderInterface;
16+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
17+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18+
19+
/**
20+
* @author Jacob Dreesen <[email protected]>
21+
*/
22+
class HttpKernelServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
23+
{
24+
/**
25+
* @var ContainerInterface
26+
*/
27+
private $container;
28+
29+
/**
30+
* @var CallbackInvoker
31+
*/
32+
private $callbackInvoker;
33+
34+
/**
35+
* @param ContainerInterface $container
36+
* @param CallbackInvoker $callbackInvoker
37+
*/
38+
public function __construct(ContainerInterface $container, CallbackInvoker $callbackInvoker)
39+
{
40+
$this->container = $container;
41+
$this->callbackInvoker = $callbackInvoker;
42+
}
43+
44+
public function register(\Pimple\Container $app)
45+
{
46+
// Override the controller resolver with ours.
47+
$app['resolver'] = function ($app) {
48+
return new ControllerResolver(
49+
$app['phpdi.callable_resolver'],
50+
new ResolverChain([
51+
new AssociativeArrayResolver,
52+
new TypeHintContainerResolver($this->container),
53+
])
54+
);
55+
};
56+
57+
// Override the callback resolver with ours.
58+
$app['callback_resolver'] = function ($app) {
59+
return new CallbackResolver(
60+
$app,
61+
$app['phpdi.callable_resolver']
62+
);
63+
};
64+
}
65+
66+
public function subscribe(\Pimple\Container $app, EventDispatcherInterface $dispatcher)
67+
{
68+
// Remove the Silex listeners first
69+
$this->removeSubscriber($dispatcher, \Silex\EventListener\MiddlewareListener::class);
70+
$this->removeSubscriber($dispatcher, \Silex\EventListener\ConverterListener::class);
71+
72+
// And register ours instead
73+
$dispatcher->addSubscriber(new MiddlewareListener($app, $this->callbackInvoker));
74+
$dispatcher->addSubscriber(new ConverterListener($app['routes'], $app['callback_resolver'], $this->callbackInvoker));
75+
}
76+
77+
/**
78+
* Removes an event subscriber by its class name.
79+
*
80+
* @param EventDispatcherInterface $dispatcher
81+
* @param string $subscriberClass
82+
*/
83+
private function removeSubscriber(EventDispatcherInterface $dispatcher, $subscriberClass)
84+
{
85+
if (!is_subclass_of($subscriberClass, EventSubscriberInterface::class, true)) {
86+
throw new \InvalidArgumentException('$subscriberClass must implement ' . EventSubscriberInterface::class);
87+
}
88+
89+
/** @var EventSubscriberInterface $subscriberClass */
90+
foreach ($subscriberClass::getSubscribedEvents() as $eventName => $params) {
91+
foreach ($dispatcher->getListeners($eventName) as $listener) {
92+
if (is_array($listener) && is_a($listener[0], $subscriberClass, true)) {
93+
$dispatcher->removeListener($eventName, $listener);
94+
}
95+
}
96+
}
97+
}
98+
}

tests/ApplicationTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public function the_callback_resolver_should_be_registered_as_a_service()
6161
{
6262
$app = new Application();
6363

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

0 commit comments

Comments
 (0)