-1

I've been put to work on a very complex Drupal 7 based system with multiple custom written modules for which the developers have gone or been re-assigned. Documentation for the system is very sparse. I think it would help me to get a a better overall picture of the system, as well as to figure out what is happening in particular parts of the system that I have been asked to fix or change, if I could see a listing of all of the hooks that are implemented.

I presume that Drupal scans all of the code in the system and builds itself some sort of structure or associative array in its cache memory so that it can quickly find any hooks that need to be invoked. Is the result stored somewhere that I can read, for example in a database table or a global variable? If I need to figure it out myself, is there a particular function, for example in the system module or bootstrap code that all hooks must pass through once? If so, perhaps I could (temporarily) hack it to get the information I want.

If someone knows how to do this, I'd love to hear how. If you don't know how to do it but have ideas about especially fruitful places to look in the code, database, drush functions, or wherever, that could be useful too.

Thank you very much.

1

1 Answer 1

0

The list of hooks implemented by modules are kept by Drupal in its cache (cache bin: cache_bootstrap, cache ID: module_implements); that is why you cannot simply edit an enabled module to add or removed hooks.
Its content is an array whose keys are the name of the hook and the values are array containing couples $module => $group (one for each module implementing a hook).
The cache is populated progressively each time a hook is invoked; so, in a fresh Drupal installation it is initially empty.

As reference, these are the relevant parts of code used by module_implements().

  // Fetch implementations from cache.
  if (empty($implementations)) {
    $implementations = cache_get('module_implements', 'cache_bootstrap');
    if ($implementations === FALSE) {
      $implementations = array();
    }
    else {
      $implementations = $implementations->data;
    }
  }
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;
  }
}

As for the functions used to invoke hooks, they are more than one, but in most cases, the modules use module_implements() (which is the function populating the hook cache), directly or indirectly. The only case where that function is not used is when a module invokes a hook of a single module, probably getting the module name from a setting or using a literal string for the module name; in this case, module_invoke() is used, even if (in the case of settings) I would expect the module to use module_implements() to populate the choices the users have.

Not the answer you're looking for? Browse other questions tagged or ask your own question.