diff --git a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php index a8e1f9611b..735784ad64 100644 --- a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php +++ b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Config\Resource; +use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + /** * @author Nicolas Grekas */ @@ -114,7 +117,9 @@ class ReflectionClassResource implements SelfCheckingResourceInterface, \Seriali private function generateSignature(\ReflectionClass $class) { - yield $class->getDocComment().$class->getModifiers(); + yield $class->getDocComment(); + yield (int) $class->isFinal(); + yield (int) $class->isAbstract(); if ($class->isTrait()) { yield print_r(class_uses($class->name), true); @@ -149,6 +154,16 @@ class ReflectionClassResource implements SelfCheckingResourceInterface, \Seriali yield print_r($defaults, true); } } + + if ($class->isSubclassOf(EventSubscriberInterface::class)) { + yield EventSubscriberInterface::class; + yield print_r(\call_user_func(array($class->name, 'getSubscribedEvents')), true); + } + + if ($class->isSubclassOf(ServiceSubscriberInterface::class)) { + yield ServiceSubscriberInterface::class; + yield print_r(\call_user_func(array($class->name, 'getSubscribedServices')), true); + } } } diff --git a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php index 4eca3d50e4..3f13096f0a 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php @@ -13,6 +13,8 @@ namespace Symfony\Component\Config\Tests\Resource; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Resource\ReflectionClassResource; +use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; class ReflectionClassResourceTest extends TestCase { @@ -136,8 +138,52 @@ EOPHP; yield array(0, 14, '/** priv docblock */'); yield array(0, 15, ''); } + + public function testEventSubscriber() + { + $res = new ReflectionClassResource(new \ReflectionClass(TestEventSubscriber::class)); + $this->assertTrue($res->isFresh(0)); + + TestEventSubscriber::$subscribedEvents = array(123); + $this->assertFalse($res->isFresh(0)); + + $res = new ReflectionClassResource(new \ReflectionClass(TestEventSubscriber::class)); + $this->assertTrue($res->isFresh(0)); + } + + public function testServiceSubscriber() + { + $res = new ReflectionClassResource(new \ReflectionClass(TestServiceSubscriber::class)); + $this->assertTrue($res->isFresh(0)); + + TestServiceSubscriber::$subscribedServices = array(123); + $this->assertFalse($res->isFresh(0)); + + $res = new ReflectionClassResource(new \ReflectionClass(TestServiceSubscriber::class)); + $this->assertTrue($res->isFresh(0)); + } } interface DummyInterface { } + +class TestEventSubscriber implements EventSubscriberInterface +{ + public static $subscribedEvents = array(); + + public static function getSubscribedEvents() + { + return self::$subscribedEvents; + } +} + +class TestServiceSubscriber implements ServiceSubscriberInterface +{ + public static $subscribedServices = array(); + + public static function getSubscribedServices() + { + return self::$subscribedServices; + } +} diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index 6f759720e6..ab26402819 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -22,7 +22,8 @@ "require-dev": { "symfony/finder": "~3.3|~4.0", "symfony/yaml": "~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0" + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/event-dispatcher": "~3.3|~4.0" }, "conflict": { "symfony/finder": "<3.3", diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php index 4ed990ac08..572eabb7d9 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php @@ -56,14 +56,14 @@ class RegisterServiceSubscribersPass extends AbstractRecursivePass } $class = $value->getClass(); - if (!is_subclass_of($class, ServiceSubscriberInterface::class)) { - if (!class_exists($class, false)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $this->currentId)); - } - + if (!$r = $this->container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $this->currentId)); + } + if (!$r->isSubclassOf(ServiceSubscriberInterface::class)) { throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $this->currentId, ServiceSubscriberInterface::class)); } - $this->container->addObjectResource($class); + $class = $r->name; + $subscriberMap = array(); $declaringClass = (new \ReflectionMethod($class, 'getSubscribedServices'))->class; diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php index 9f9c09c528..ff636d6180 100644 --- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -89,17 +89,15 @@ class RegisterListenersPass implements CompilerPassInterface $def = $container->getDefinition($id); // We must assume that the class value has been correctly filled, even if the service is created by a factory - $class = $container->getParameterBag()->resolveValue($def->getClass()); - $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; + $class = $def->getClass(); - if (!is_subclass_of($class, $interface)) { - if (!class_exists($class, false)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } - $container->addObjectResource($class); + if (!$r->isSubclassOf(EventSubscriberInterface::class)) { + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EventSubscriberInterface::class)); + } + $class = $r->name; ExtractingEventDispatcher::$subscriber = $class; $extractingDispatcher->addSubscriber($extractingDispatcher);