function hook_module_implements_alter

You are here

7 system.api.php hook_module_implements_alter(&$implementations, $hook)
8 system.api.php hook_module_implements_alter(&$implementations, $hook)

Alter the registry of modules implementing a hook.

This hook is invoked during module_implements(). A module may implement this hook in order to reorder the implementing modules, which are otherwise ordered by the module's system weight.

Note that hooks invoked using drupal_alter() can have multiple variations (such as hook_form_alter() and hook_form_FORM_ID_alter()). drupal_alter() will call all such variants defined by a single module in turn. For the purposes of hook_module_implements_alter(), these variants are treated as a single hook. Thus, to ensure that your implementation of hook_form_FORM_ID_alter() is called at the right time, you will have to change the order of hook_form_alter() implementation in hook_module_implements_alter().

Parameters

$implementations: An array keyed by the module's name. The value of each item corresponds to a $group, which is usually FALSE, unless the implementation is in a file named $module.$group.inc.

$hook: The name of the module hook being implemented.

Related topics

1 function implements hook_module_implements_alter()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

common_test_module_implements_alter in modules/simpletest/tests/common_test.module
Implements hook_module_implements_alter().
2 invocations of hook_module_implements_alter()
drupal_alter in includes/module.inc
Passes alterable variables to specific hook_TYPE_alter() implementations.
module_implements in includes/module.inc
Determines which modules are implementing a hook.

File

modules/system/system.api.php, line 2009
Hooks provided by Drupal core and the System module.

Code

function hook_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'rdf_mapping') {
    // Move my_module_rdf_mapping() to the end of the list. module_implements()
    // iterates through $implementations with a foreach loop which PHP iterates
    // in the order that the items were added, so to move an item to the end of
    // the array, we remove it and then add it.
    $group = $implementations['my_module'];
    unset($implementations['my_module']);
    $implementations['my_module'] = $group;
  }
}

Comments

This seems to be substantially non-functional...

It looks like it's called early in the request, for hooks like hook_boot, before most modules have been loaded. The list of modules implementing this hook is cached at that time and not re-calculated once all modules are loaded.

This means that the hook works only for very core modules, such as entity, plus under various unusual circumstances such as "drush cc all". It doesn't work for ordinary modules serving normal requests.

The reason it may seem like this hook is not invoked is because each hook is added to the registry only when needed. After a cache clear, only basic core hooks are needed to generate the page. However this hook is called everytime any new hook is called for the first time after a cache clear. Then you have an opportunity to rearrange the hook order or even remove implementations. The modifications will be saved into the cache.

hook_module_implements_alter() seems to be not usable in any module that isn't a bootstrap module, because the list of implementations is cached very early. If you put a hook_boot in your module and then clear cache a lot and esnure that the list of bootstrap modules is properly regenerated, that seems to make this hook fire.

Addendum: This is only true if you have another module that uses hook_boot that calls module_implements. However, at least one authentication system module does this. Others might as well.

There are two issues saying that calling module_implements() from within a hook_boot invocation is just plain disallowed / unsupported, and that this should be documented as such (or even an exception thrown if code does this, to prevent hard to trace bugs): 496170 and 1415278.

The first issue could probably benefit from the names of any modules that do this. I couldn't find this authentication system module.

The theme/template version of this hook can be found at hook_theme_registry_alter

The documentation above shows a way of making a module always execute it's hook last, but what about if you want a module to always execute first?

This is how I did it:

function my_module_module_implements_alter(&$implementations, $hook) {
  if ($hook != 'the_hook_to_change') {
    return;
  }

  $module = 'my_module';
  $group = array($module => $implementations[$module]);
  unset($implementations[$module]);
  $implementations = $group + $implementations;
}

This will make my_module's hook always run before any other module.

Thanks @acbramley this did the trick!

Impossible to unset hook_field_storage_load() or hook_field_storage_write(), is there any other way to turn off that hooks?

If you have a hook_form_FORM_ID_alter() in your module, and you want it to execute last...

<?php
function my_module_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'form_alter' && isset($implementations['my_module'])) {
    $group = $implementations['my_module'];
    unset($implementations['my_module']);
    $implementations['my_module'] = $group;
  }
}
?>

The module_implements_alter() will always be called with the base hook, even if you are implementing something different. The extra isset on the $implementations array is needed in case you don't actually implement hook_form_alter() as well.

I had to implement an empty hook_form_alter and have this in hook_module_implements_alter:

<?php
if ($hook == 'form_node_form_alter' || $hook == 'form_alter') {
?>

bofore my hook_form_node_form_alter was moved to the end of the line.

Note that hook_url_inbound_alter() implementations are called in reverse order, see includes/path.inc:

<?php
 
// Allow other modules to alter the inbound URL. We cannot use drupal_alter()
  // here because we need to run hook_url_inbound_alter() in the reverse order
  // of hook_url_outbound_alter().
 
foreach (array_reverse(module_implements('url_inbound_alter')) as $module) {
   
$function = $module . '_url_inbound_alter';
   
$function($path, $original_path, $path_language);
  }
?>