function ModuleHandler::getCombinedListeners
Builds a list of implementations for an alter hook.
Parameters
list<string> $hooks: The hooks passed to the ->alter() call.
Return value
list<callable> List of implementation callables.
1 call to ModuleHandler::getCombinedListeners()
- ModuleHandler::alter in core/
lib/ Drupal/ Core/ Extension/ ModuleHandler.php - Passes alterable variables to specific hook_TYPE_alter() implementations.
File
-
core/
lib/ Drupal/ Core/ Extension/ ModuleHandler.php, line 473
Class
- ModuleHandler
- Class that manages modules in a Drupal installation.
Namespace
Drupal\Core\ExtensionCode
protected function getCombinedListeners(array $hooks) : array {
// Get implementation lists for each hook.
/** @var list<\Drupal\Core\Hook\ImplementationList> $lists */
$lists = array_map($this->getHookImplementationList(...), $hooks);
// Remove empty lists.
/** @var array<int, \Drupal\Core\Hook\ImplementationList> $lists */
$lists = array_filter($lists, fn(ImplementationList $list) => $list->hasImplementations());
if (!$lists) {
// No implementations exist.
return [];
}
if (array_keys($lists) === [
0,
]) {
// Only the first hook has implementations.
return $lists[0]->listeners;
}
// Collect the lists from each hook and group the listeners by module.
$listeners_by_identifier = [];
$modules_by_identifier = [];
$identifiers_by_module = [];
foreach ($lists as $list) {
foreach ($list->iterateByModule() as $module => $listener) {
$identifier = is_array($listener) ? get_class($listener[0]) . '::' . $listener[1] : $listener;
$other_module = $modules_by_identifier[$identifier] ?? NULL;
if ($other_module !== NULL) {
$this->triggerErrorForDuplicateAlterHookListener($hooks, $module, $other_module, $listener, $identifier);
// Don't add the same listener more than once.
continue;
}
$listeners_by_identifier[$identifier] = $listener;
$modules_by_identifier[$identifier] = $module;
$identifiers_by_module[$module][] = $identifier;
}
}
// First we get the the modules in moduleList order, this order is module
// weight then alphabetical. Then we apply legacy ordering using
// hook_module_implements_alter(). Finally we order using order attributes.
$modules = array_keys($identifiers_by_module);
$modules = $this->reOrderModulesForAlter($modules, $hooks[0]);
// Create a flat list of identifiers, using the new module order.
$identifiers = array_merge(...array_map(fn(string $module) => $identifiers_by_module[$module], $modules));
foreach ($hooks as $hook) {
foreach ($this->getHookOrderingRules($hook) as $rule) {
$rule->apply($identifiers, $modules_by_identifier);
// Order operations must not:
// - Insert duplicate keys.
// - Change the array to be not a list.
// - Add or remove values.
assert($identifiers === array_unique($identifiers));
assert(array_is_list($identifiers));
assert(!array_diff($identifiers, array_keys($modules_by_identifier)));
assert(!array_diff(array_keys($modules_by_identifier), $identifiers));
}
}
return array_map(static fn(string $identifier) => $listeners_by_identifier[$identifier], $identifiers);
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.