diff --git a/core/core.events.yml b/core/core.events.yml index baa3323..87d00fd 100644 --- a/core/core.events.yml +++ b/core/core.events.yml @@ -14,9 +14,9 @@ subscribers: kernel.request: # Priority must be higher than LanguageRequestSubscriber as LanguageManager # access global $user in case language module enabled. - - callback: authentication_subscriber:onKernelRequestAuthenticate + - callback: Drupal\Core\EventSubscriber\AuthenticationSubscriber::onKernelRequestAuthenticate priority: 300 - - callback: language_request_subscriber:onKernelRequestLanguage + - callback: Drupal\Core\EventSubscriber\LanguageRequestSubscriber::onKernelRequestLanguage priority: 255 - callback: path_subscriber:onKernelRequestConvertPath priority: 200 diff --git a/core/core.services.yml b/core/core.services.yml index 072d017..2f04e89 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -469,18 +469,11 @@ services: arguments: ['@module_handler'] config_global_override_subscriber: class: Drupal\Core\EventSubscriber\ConfigGlobalOverrideSubscriber - tags: - - { name: event_subscriber } config_import_subscriber: class: Drupal\Core\EventSubscriber\ConfigImportSubscriber - tags: - - { name: event_subscriber } config_snapshot_subscriber: class: Drupal\Core\EventSubscriber\ConfigSnapshotSubscriber arguments: ['@config.storage', '@config.storage.snapshot'] - language_request_subscriber: - class: Drupal\Core\EventSubscriber\LanguageRequestSubscriber - arguments: ['@language_manager', '@string_translation'] exception_controller: class: Drupal\Core\Controller\ExceptionController arguments: ['@content_negotiation'] @@ -623,9 +616,6 @@ services: class: Drupal\Core\Authentication\Provider\Cookie tags: - { name: authentication_provider, priority: 0 } - authentication_subscriber: - class: Drupal\Core\EventSubscriber\AuthenticationSubscriber - arguments: ['@authentication'] current_user: class: Drupal\Core\Session\AccountInterface factory_method: authenticate diff --git a/core/lib/Drupal/Core/EventListenerPass.php b/core/lib/Drupal/Core/EventListenerPass.php index 21c97b9..d376d6e 100644 --- a/core/lib/Drupal/Core/EventListenerPass.php +++ b/core/lib/Drupal/Core/EventListenerPass.php @@ -12,7 +12,11 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Reference; +/** + * Registers event listeners based on $provider.events.yml files. + */ class EventListenerPass implements CompilerPassInterface { /** @@ -33,7 +37,7 @@ public function process(ContainerBuilder $container) { * Find the event listeners in event.yml files and add it to the container. * * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container - * The container to add event services to. + * The container to add the event services to. * @param \Symfony\Component\DependencyInjection\Definition $event_dispatcher_definition * The event dispatcher service definition. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler @@ -50,6 +54,19 @@ protected function findListeners(ContainerBuilder $container, Definition $event_ } } + /** + * Prepares method name and method arguments to register events in the DIC. + * + * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container + * The container to add the event services to. + * @param string $event_id + * The name of the event. + * @param mixed $listener + * The listener information defined in the yml file. + * + * @return array + * An array with the method name and arguments. + */ protected function prepareListener(ContainerBuilder $container, $event_id, $listener) { if (is_array($listener)) { $callback = $listener['callback']; @@ -75,14 +92,46 @@ protected function prepareListener(ContainerBuilder $container, $event_id, $list return array($add_method, $args); } + /** + * Defines a service for a given class and returns the service name. + * + * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container + * The dependency injection container builder. + * @param string $class + * The class to be used for the service. + * + * @return string + * The defined service name. + */ protected function defineService(ContainerBuilder $container, $class) { $definition = new Definition(); $definition->setClass($class); $name = 'event_listener.' . str_replace("\\", '.', $class); + + if (in_array('Drupal\Core\DependencyInjection\ContainerInjectionInterface', class_implements($class))) { + $definition->setFactoryMethod('create'); + $definition->setFactoryClass($class); + $definition->addArgument(new Reference('service_container')); + } + $container->setDefinition($name, $definition); return $name; } + /** + * Parses the callback to distinct services and callbacks. + * + * @param string $callback + * The defined callback in the yml file. + * + * @return array + * An array containing either specific service name and method or class name + * and method. + * @throws \LogicException + * Thrown, when the event definitions had the wrong input. + * @throws \InvalidArgumentException + * Thrown when the specific class does not exist. + */ protected function parseCallback($callback) { // TODO: This logic should abstracted somewhere. diff --git a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php index 91041cf..b4abd3f 100644 --- a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php @@ -8,6 +8,8 @@ namespace Drupal\Core\EventSubscriber; use Drupal\Core\Authentication\AuthenticationProviderInterface; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; @@ -18,7 +20,7 @@ * * Trigger authentication and cleanup during the request. */ -class AuthenticationSubscriber { +class AuthenticationSubscriber implements ContainerInjectionInterface { /** * Authentication provider. @@ -38,6 +40,13 @@ public function __construct(AuthenticationProviderInterface $authentication_prov } /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static($container->get('authentication')); + } + + /** * Authenticates user on request. * * @see \Drupal\Core\Authentication\AuthenticationProviderInterface::authenticate() diff --git a/core/lib/Drupal/Core/EventSubscriber/LanguageRequestSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/LanguageRequestSubscriber.php index d50022d..96f23f8 100644 --- a/core/lib/Drupal/Core/EventSubscriber/LanguageRequestSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/LanguageRequestSubscriber.php @@ -7,18 +7,18 @@ namespace Drupal\Core\EventSubscriber; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageManager; use Drupal\Core\StringTranslation\Translator\TranslatorInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Sets the $request property on the language manager. */ -class LanguageRequestSubscriber implements EventSubscriberInterface { +class LanguageRequestSubscriber implements ContainerInjectionInterface { /** * The language manager service. @@ -49,6 +49,13 @@ public function __construct(LanguageManager $language_manager, TranslatorInterfa } /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static($container->get('language_manager'), $container->get('string_translation')); + } + + /** * Sets the request on the language manager. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event @@ -64,16 +71,4 @@ public function onKernelRequestLanguage(GetResponseEvent $event) { } } - /** - * Registers the methods in this class that should be listeners. - * - * @return array - * An array of event listener definitions. - */ - static function getSubscribedEvents() { - $events[KernelEvents::REQUEST][] = array('onKernelRequestLanguage', 255); - - return $events; - } - } diff --git a/core/tests/Drupal/Tests/Core/EventListenerPassTest.php b/core/tests/Drupal/Tests/Core/EventListenerPassTest.php index d477041..37fdc76 100644 --- a/core/tests/Drupal/Tests/Core/EventListenerPassTest.php +++ b/core/tests/Drupal/Tests/Core/EventListenerPassTest.php @@ -8,10 +8,12 @@ namespace Drupal\Tests\Core; use Drupal\Component\Discovery\DiscoverableInterface; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\EventListenerPass; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Tests\UnitTestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; /** @@ -145,6 +147,34 @@ public function testEventWithPriority() { } /** + * Tests the event listener pass with static factory method event subscribers. + */ + public function testEventWithStaticFactoryMethod() { + $container = $this->setUpContainer(); + + $info['subscribers']['example'][] = array( + 'callback' => 'Drupal\Tests\Core\TestClass2::subscriberMethod', + 'priority' => 10, + ); + $yaml_discovery = $this->getMock('Drupal\Component\Discovery\DiscoverableInterface'); + $yaml_discovery->expects($this->once()) + ->method('findAll') + ->will($this->returnValue(array($info))); + + $this->eventListenerPass->setYamlDiscovery($yaml_discovery); + $this->eventListenerPass->process($container); + + + $definition = $container->getDefinition('event_dispatcher'); + $expected_calls = array(); + $expected_calls[] = array('addListenerService', array('example', array('event_listener.Drupal.Tests.Core.TestClass', 'subscriberMethod'), 10)); + $this->assertEquals($expected_calls, $definition->getMethodCalls()); + + $this->assertEquals('Drupal\Tests\Core\TestClass2', $definition->getFactoryClass()); + $this->assertEquals('create', $definition->getFactoryMethod()); + } + + /** * Tests the event listener pass with one service based event. */ public function testServiceEventWithoutPriority() { @@ -281,3 +311,16 @@ class TestClass { public function subscriberMethod() {} public function subscriberMethod2() {} } + +class TestClass2 implements ContainerInjectionInterface { + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static(); + } + + public function subscriberMethod() {} + +}