Using hook_requirements In Drupal 6.x

Photo of Greg Harvey
Tue, 2009-01-27 18:25By greg

You probably know about dependencies in modules and how to declare them in a module's .info file. In case you're not familiar with the concept, it looks like this:

dependencies[] = imagefield
dependencies[] = nodereference
dependencies[] = content_copy
dependencies[] = views
dependencies[] = imagecache

(Slightly different in Drupal 5.x - be warned!)

Each one of those modules must be enabled before Drupal will allow you to enable the module you want to install. Neat, huh? But there is a problem:

If the depended-upon modules exist but are not yet enabled, Drupal offers to enable them for you. What it doesn't tell you is that it will enable those modules, and the original module you wished to install, in an arbitrary order. Either that or it enables them all at once in the same process. Either way, it will *not* enable all the dependencies and then enable the initial module separately, as you might expect and as would be truly "safe" behaviour.

This can cause problems if your hook_install() (the function containing code you wish to execute on installation of your module) contains calls to functions within those modules. Those functions will not be available, because the module is not yet loaded in. A case in point is my CCK Gallery module, which tries to drupal_execute() a form presented by the Content Copy module and calls functions within the ImageCache module. If they're not available, the installation fails in an ugly way, and if they weren't installed prior to CCK Gallery then they will *not* be available, even though Drupal tells you it will install them for you.

Note, I pitched in a Drupal 7.x feature request along these lines:
http://drupal.org/node/365098

The way around this for Drupal developers using Drupal 5.x and above is to have a hook_requirements() which can check for the existence of various things before installing and abort if they're not there:
http://api.drupal.org/api/function/hook_requirements

I'm not going to go in to massive detail, because you can RTFM like I had to, but here is my hook implementation for your reference. It successfully aborts installing CCK Gallery if the functions I need aren't available for any reason, thus getting around the ugly failure I was seeing:

/**
* Implementation of hook_requirements()
*/
function cck_gallery_requirements($phase) {
$requirements = array();
$t = get_t();

switch ($phase) {
case 'install':
$error = FALSE;
if (!module_exists('content_copy')) {
$error = TRUE;
$value = $t('Content Copy module to be pre-installed.');
$severity = REQUIREMENT_ERROR;
}

if (!module_exists('imagecache')) {
if ($error) {
$value .= $t(' ImageCache module to be pre-installed.');
} else {
$error = TRUE;
$value .= $t('ImageCache module to be pre-installed.');
}
$severity = REQUIREMENT_ERROR;
}

if ($error) {
$requirements['cck_gallery'] = array(
'title' => $t('CCK Gallery requirements'),
'value' => $value . $t(' If the required modules are now installed, please enable CCK Gallery again.'),
'severity' => $severity,
);
}
break;
}

return $requirements;
}
?>

It seems any module calling functions in another module that isn't required core really *must* implement hook_requirements() in it's .install file.