Sunday 13 February 2011

Blocks and hook_hook_info()

As an ongoing attempt to keep the amount of code loaded for any given page down to a minimum the Drupal 7 developers came up with hook_hook_info() - which is a completely different hook from the one in Drupal 6.

What this hook does is allow a module to define a "group" for its hooks, so the system itself defines the group "tokens" for any token-related hook.

Which means that, when attempting to find implementations of the hook the core checks to see whether a module has a file modulename.tokens.inc - and if it does, it loads that before looking for the token hook. (And records if it finds it in the .inc file.)

This is all good and allows modules to put its token-related hooks in a file that isn't loaded unless its needed.

But 'tokens' is the only group defined for core hooks. Which seems a bit of a waste.

So one thing I've done is to intercept hook_hook_info_alter() and my own group for blocks, like this:


/**
 * Implements hook_hook_info_alter().
 */
function mymodule_hook_info_alter(&$hooks) {
  static $myhooks = array(
    'blocks' => array('block_configure', 'block_view_alter', 'block_view', 'block_save', 'block_list_alter', 'block_info_alter', 'block_info')
  );
  foreach ($myhooks as $group => $items) {
    foreach ($items as $hook) {
      $hooks[$hook] = array('group' => $group);
    }
  }
}

And that's all you need. So you can now happily put your block-related hooks into modulename.blocks.inc. This is not future-proofed, you should really check to see whether the hook has been defined already before doing this, just to be completely safe.

One point worth noting is that there is now a hook_view_BLOCK_DELTA_alter() as well, which you can't put in a group specifically because you'd need an entry for every defined block. However it's not a problem because that hook is called immediately after hook_view_alter() - which will ensure that the .inc file is loaded first.

Don't bother trying to put node hooks into a separate file - it won't work because the node module just goes its own way and doesn't use the hook_info data.

No comments: