function module_implements in Drupal 7
Same name and namespace in other branches
- 4 includes/module.inc \module_implements()
- 5 includes/module.inc \module_implements()
- 6 includes/module.inc \module_implements()
Determines which modules are implementing a hook.
Lazy-loaded include files specified with "group" via hook_hook_info() or hook_module_implements_alter() will be automatically included by this function when necessary.
Parameters
string $hook: The name of the hook (e.g. "help" or "menu").
bool $sort: By default, modules are ordered by weight and filename, settings this option to TRUE, module list will be ordered by module name.
bool $reset: For internal use only: Whether to force the stored list of hook implementations to be regenerated (such as after enabling a new module, before processing hook_enable).
Return value
An array with the names of the modules which are implementing this hook.
See also
module_implements_write_cache()
Related topics
68 calls to module_implements()
- aggregator_admin_form in modules/
aggregator/ aggregator.admin.inc - Form constructor for the aggregator system settings.
- block_form_system_performance_settings_alter in modules/
block/ block.module - Implements hook_form_FORM_ID_alter().
- boot_test_1_boot in modules/
simpletest/ tests/ boot_test_1.module - Implements hook_boot().
- DrupalDefaultEntityController::attachLoad in includes/
entity.inc - Attaches data to entities upon loading.
- DrupalWebTestCase::tearDown in modules/
simpletest/ drupal_web_test_case.php - Delete created files and temporary files directory, delete the tables created by setUp(), and reset the database prefix.
3 string references to 'module_implements'
- ModuleUnitTest::testModuleImplements in modules/
simpletest/ tests/ module.test - Test module_implements() caching.
- module_implements_write_cache in includes/
module.inc - Writes the hook implementation cache.
- _drupal_bootstrap_full in includes/
common.inc
File
- includes/
module.inc, line 726 - API for loading and interacting with Drupal modules.
Code
function module_implements($hook, $sort = FALSE, $reset = FALSE) {
// Use the advanced drupal_static() pattern, since this is called very often.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['implementations'] =& drupal_static(__FUNCTION__);
$drupal_static_fast['verified'] =& drupal_static(__FUNCTION__ . ':verified');
}
$implementations =& $drupal_static_fast['implementations'];
$verified =& $drupal_static_fast['verified'];
// We maintain a persistent cache of hook implementations in addition to the
// static cache to avoid looping through every module and every hook on each
// request. Benchmarks show that the benefit of this caching outweighs the
// additional database hit even when using the default database caching
// backend and only a small number of modules are enabled. The cost of the
// cache_get() is more or less constant and reduced further when non-database
// caching backends are used, so there will be more significant gains when a
// large number of modules are installed or hooks invoked, since this can
// quickly lead to module_hook() being called several thousand times
// per request.
if ($reset) {
$implementations = array();
$verified = array();
cache_set('module_implements', array(), 'cache_bootstrap');
drupal_static_reset('module_hook_info');
drupal_static_reset('drupal_alter');
cache_clear_all('hook_info', 'cache_bootstrap');
cache_clear_all('system_cache_tables', 'cache');
return;
}
// Fetch implementations from cache.
// This happens on the first call to module_implements(*, *, FALSE) during a
// request, but also when $implementations have been reset, e.g. after
// module_enable().
if (empty($implementations)) {
$implementations = cache_get('module_implements', 'cache_bootstrap');
if ($implementations === FALSE) {
$implementations = array();
}
else {
$implementations = $implementations->data;
}
// Forget all previously "verified" hooks, in case that $implementations
// were cleared via drupal_static_reset('module_implements') instead of
// module_implements(*, *, TRUE).
$verified = array();
}
if (!isset($implementations[$hook])) {
// The hook is not cached, so ensure that whether or not it has
// implementations, that the cache is updated at the end of the request.
$implementations['#write_cache'] = TRUE;
// Discover implementations for this hook.
$hook_info = module_hook_info();
$implementations[$hook] = array();
$list = module_list(FALSE, FALSE, $sort);
foreach ($list as $module) {
$include_file = isset($hook_info[$hook]['group']) && module_load_include('inc', $module, $module . '.' . $hook_info[$hook]['group']);
// Since module_hook() may needlessly try to load the include file again,
// function_exists() is used directly here.
if (function_exists($module . '_' . $hook)) {
$implementations[$hook][$module] = $include_file ? $hook_info[$hook]['group'] : FALSE;
}
}
// Allow modules to change the weight of specific implementations, but avoid
// an infinite loop.
if ($hook != 'module_implements_alter') {
// Remember the implementations before hook_module_implements_alter().
$implementations_before = $implementations[$hook];
drupal_alter('module_implements', $implementations[$hook], $hook);
// Verify implementations that were added or modified.
foreach (array_diff_assoc($implementations[$hook], $implementations_before) as $module => $group) {
// If drupal_alter('module_implements') changed or added a $group, the
// respective file needs to be included.
if ($group) {
module_load_include('inc', $module, "{$module}.{$group}");
}
// If a new implementation was added, verify that the function exists.
if (!function_exists($module . '_' . $hook)) {
unset($implementations[$hook][$module]);
}
}
}
// Implementations for this hook are now "verified".
$verified[$hook] = TRUE;
}
elseif (!isset($verified[$hook])) {
// Implementations for this hook were in the cache, but they are not
// "verified" yet.
foreach ($implementations[$hook] as $module => $group) {
// If this hook implementation is stored in a lazy-loaded file, so include
// that file first.
if ($group) {
module_load_include('inc', $module, "{$module}.{$group}");
}
// It is possible that a module removed a hook implementation without the
// implementations cache being rebuilt yet, so we check whether the
// function exists on each request to avoid undefined function errors.
// Since module_hook() may needlessly try to load the include file again,
// function_exists() is used directly here.
if (!function_exists($module . '_' . $hook)) {
// Clear out the stale implementation from the cache and force a cache
// refresh to forget about no longer existing hook implementations.
unset($implementations[$hook][$module]);
$implementations['#write_cache'] = TRUE;
}
}
$verified[$hook] = TRUE;
}
return array_keys($implementations[$hook]);
}