Theme hooks vs module hooks

by hamahama   Last Updated August 13, 2019 21:07 PM - source

Sometimes when I try to apply a hook, just to realise it's supposed to be in a module file.

Is there a way of knowing what hooks can be implemented in a theme's template.php file, or one in a module?

Tags : hooks


Answers 1


Generally speaking, only alter hooks can be implemented by themes, which means hooks like hook_form_alter() and hook_menu_alter(), or in short all those hooks that are invoked through drupal_alter() in Drupal 7 and lower (ModuleHandler()::alter() or ThemeManager::alter() in Drupal 8).

Other hooks, which are invoked by module_invoke_all() (ModuleHandler::invokeAll() in Drupal 8), don't get invoked for themes simply for fact the code doesn't check if the currently enabled theme defines any hook.

  foreach (module_implements($hook) as $module) {
    $function = $module . '_' . $hook;
    if (function_exists($function)) {
      $result = call_user_func_array($function, $args);
      if (isset($result) && is_array($result)) {
        $return = array_merge_recursive($return, $result);
      }
      elseif (isset($result)) {
        $return[] = $result;
      }
    }
  }

In Drupal 8, where the ModuleHandler class invokes hooks implemented from modules and the ThemeManager class invokes hooks implemented by themes, only the first class implements invoke() and invokeAll(). This means that in Drupal 8 theme hooks aren't invoked, by Drupal core.

This is valid for Drupal core hooks, and mostly all the hooks used by third-party modules. It is then up to a module to verify a hook is implemented by a theme too, and invoke it. This is what the Views module does.

  // Let modules modify the view just prior to rendering it.
  foreach (module_implements('views_pre_render') as $module) {
    $function = $module . '_views_pre_render';
    $function($this);
  }

  // Let the themes play too, because pre render is a very themey thing.
  foreach ($GLOBALS['base_theme_info'] as $base) {
    $function = $base->name . '_views_pre_render';
    if (function_exists($function)) {
      $function($this);
    }
  }
  $function = $GLOBALS['theme'] . '_views_pre_render';
  if (function_exists($function)) {
    $function($this);
  }

For hooks used by third-party modules, you need to check the code used to invoke them. Chances are that only alter hooks are invoked for themes, but in some cases also other hooks could be implemented by themes.
Keep in mind that in the case of themes, not all the enabled themes are checked for hook implementations, contrary to what happens with modules. Only the currently used theme and the base themes are checked, as done from the Views module.

kiamlaluno
kiamlaluno
May 06, 2015 05:24 AM

Related Questions


How to find hooks being called by a Drupal page?

Updated April 03, 2015 21:20 PM

Modify text of error message for required field

Updated April 22, 2015 20:03 PM


Where are hooks stored/cached?

Updated April 13, 2015 20:03 PM