public TaggedHandlersPass::process(ContainerBuilder $container)
Finds services tagged with 'service_collector', then finds all corresponding tagged services and adds a method call for each to the consuming/collecting service definition.
Supported 'service_collector' tag attributes:
- tag: The tag name used by handler services to collect. Defaults to the service ID of the consumer.
-
call: The method name to call on the consumer service. Defaults to 'addHandler'. The called method receives two arguments:
- The handler instance as first argument.
- Optionally the handler's priority as second argument, if the method accepts a second parameter and its name is "priority". In any case, all handlers registered at compile time are sorted already.
- required: Boolean indicating if at least one handler service is required. Defaults to FALSE.
Example (YAML):
tags: - { name: service_collector, tag: breadcrumb_builder, call: addBuilder }
Supported handler tag attributes:
- priority: An integer denoting the priority of the handler. Defaults to 0.
Example (YAML):
tags: - { name: breadcrumb_builder, priority: 100 }
Throws
\Symfony\Component\DependencyInjection\Exception\LogicException If the method of a consumer service to be called does not type-hint an interface.
\Symfony\Component\DependencyInjection\Exception\LogicException If a tagged handler does not implement the required interface.
\Symfony\Component\DependencyInjection\Exception\LogicException If at least one tagged service is required but none are found.
Overrides CompilerPassInterface::process
File
- core/lib/Drupal/Core/DependencyInjection/Compiler/TaggedHandlersPass.php, line 77
Class
- TaggedHandlersPass
- Collects services to add/inject them into a consumer service.
Namespace
Drupal\Core\DependencyInjection\Compiler
Code
public function process(ContainerBuilder $container) { foreach ($container->findTaggedServiceIds('service_collector') as $consumer_id => $passes) { foreach ($passes as $pass) { $tag = isset($pass['tag']) ? $pass['tag'] : $consumer_id; $method_name = isset($pass['call']) ? $pass['call'] : 'addHandler'; $required = isset($pass['required']) ? $pass['required'] : FALSE; // Determine parameters. $consumer = $container->getDefinition($consumer_id); $method = new \ReflectionMethod($consumer->getClass(), $method_name); $params = $method->getParameters(); $interface_pos = 0; $id_pos = NULL; $priority_pos = NULL; $extra_params = []; foreach ($params as $pos => $param) { if ($param->getClass()) { $interface = $param->getClass(); } elseif ($param->getName() === 'id') { $id_pos = $pos; } elseif ($param->getName() === 'priority') { $priority_pos = $pos; } else { $extra_params[$param->getName()] = $pos; } } // Determine the ID. if (!isset($interface)) { throw new LogicException(vsprintf("Service consumer '%s' class method %s::%s() has to type-hint an interface.", array( $consumer_id, $consumer->getClass(), $method_name, ))); } $interface = $interface->getName(); // Find all tagged handlers. $handlers = array(); $extra_arguments = array(); foreach ($container->findTaggedServiceIds($tag) as $id => $attributes) { // Validate the interface. $handler = $container->getDefinition($id); if (!is_subclass_of($handler->getClass(), $interface)) { throw new LogicException("Service '$id' for consumer '$consumer_id' does not implement $interface."); } $handlers[$id] = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; // Keep track of other tagged handlers arguments. foreach ($extra_params as $name => $pos) { $extra_arguments[$id][$pos] = isset($attributes[0][$name]) ? $attributes[0][$name] : $params[$pos]->getDefaultValue(); } } if (empty($handlers)) { if ($required) { throw new LogicException(sprintf("At least one service tagged with '%s' is required.", $tag)); } continue; } // Sort all handlers by priority. arsort($handlers, SORT_NUMERIC); // Add a method call for each handler to the consumer service // definition. foreach ($handlers as $id => $priority) { $arguments = array(); $arguments[$interface_pos] = new Reference($id); if (isset($priority_pos)) { $arguments[$priority_pos] = $priority; } if (isset($id_pos)) { $arguments[$id_pos] = $id; } // Add in extra arguments. if (isset($extra_arguments[$id])) { // Place extra arguments in their right positions. $arguments += $extra_arguments[$id]; } // Sort the arguments by position. ksort($arguments); $consumer->addMethodCall($method_name, $arguments); } } } }
Please login to continue.