diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventListenersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventListenersPass.php index 9377043..d9e8242 100644 --- a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventListenersPass.php +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventListenersPass.php @@ -22,8 +22,43 @@ public function process(ContainerBuilder $container) { $definition = $container->getDefinition('event_dispatcher'); $event_subscriber_info = []; - foreach ($container->findTaggedServiceIds('event_subscriber') as $id => $attributes) { + $module_parameter = $container->hasParameter('container.modules') ? $container->getParameter('container.modules') : []; + + // First collect all tagged services in order to sort them by module weight + // and class name. + + $weights = []; + // First figure out all module weights. + $ids = array_keys($container->findTaggedServiceIds('event_subscriber')); + $id_class_map = []; + foreach ($ids as $id) { + $class = $container->getDefinition($id)->getClass(); + $id_class_map[$id] = $class; + + list($drupal, $provider, $rest) = explode('\\', $class, 3); + + if ($drupal == 'Drupal' && isset($module_parameter[$provider]['weight'])) { + $weight = $module_parameter[$provider]['weight']; + } + else { + $weight = 0; + } + $weights[$id] = $weight; + } + + // Sort the IDs first by module weight, than by full classname. Using the + // full classname takes into account the module name automatically. + usort($ids, function($a, $b) use ($weights, $id_class_map) { + if ($weights[$a] !== $weights[$b]) { + return $weights[$a] < $weights[$b] ? -1 : 1; + } + else { + return $id_class_map[$a] < $id_class_map[$b] ? -1 : 1; + } + }); + + foreach ($ids as $id) { // We must assume that the class value has been correctly filled, even if the service is created by a factory $class = $container->getDefinition($id)->getClass(); diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index c014e4a..fe3a55e 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -1193,6 +1193,7 @@ protected function getModulesParameter() { 'type' => $data->getType(), 'pathname' => $data->getPathname(), 'filename' => $data->getExtensionFilename(), + 'weight' => $weight, ); } } diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/RegisterEventListenersPassTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/RegisterEventListenersPassTest.php index af1611f..a9ef0d4 100644 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/RegisterEventListenersPassTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/RegisterEventListenersPassTest.php @@ -90,6 +90,14 @@ public function testProcessWithMultipleSubscribersWithModuleWeightAndSamePriorit $builder = new ContainerBuilder(); $event_dispatcher_definition = $builder->register('event_dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher'); + $builder->setParameter('container.modules', [ + 'register_event_listener_pass_test_nodule' => [ + 'weight' => -10, + ], + 'register_event_listener_pass_test_module' => [ + 'weight' => 0, + ], + ]); $builder->register('test_service_0', 'Drupal\register_event_listener_pass_test_module\TestService1') ->addTag('event_subscriber'); @@ -100,8 +108,10 @@ public function testProcessWithMultipleSubscribersWithModuleWeightAndSamePriorit $listeners = $event_dispatcher_definition->getArguments()[0]; $this->assertEquals([ - 10 => [['service' => ['test_service_1', 'onExample']]], - 0 => [['service' => ['test_service_0', 'onExample']]] + 0 => [ + ['service' => ['test_service_1', 'onExample']], + ['service' => ['test_service_0', 'onExample']], + ], ], $listeners['example']); }