Enabling Drupal modules in update hooks

It is becoming more and more common with instances of continuous integration and testing to do any configuration through code. This is true of enabling modules as well reverting Features using hook_update_N() to carry those actions out. The problem with just putting module_enable() in an update hook is that even if the module enable fails, the hook_update_N is considered a success, so there is no way to re-run the specific hook_update. With a pair of helper functions, it is possible for the update hook to be considered a failure if a module does not enable. Considering it a failure allows you to resolve the issue and re-attempt the update hook.

Here is what the update hook to enable two modules might look like. Notice it calls a custom function rather than just module_enable().

<?php
/**
 * Enables book and og_book.
 */
function mymodule_update_7001(&$sandbox) {
 
$modules = array(
   
'book',
   
'og_book',
  );
 
$return = mymodule_module_enable($modules);

  return $return;
}
?>

Here are the two helper functions that enable the modules and check to makes sure they were actually enabled.

<?php
/**
 * Check to see if the modules are actually enabled.
 *
 * @param array $modules
 *   An array of module machine names to check for being enabled.
 *
 * @return string
 *   Messsage indicating the modules are enabled
 *
 * @throws DrupalUpdateException
 *   Calls the update a failure, preventing it from registering the update_N.
 */
function mymodule_check_modules_enabled($modules = array()) {
 
$modules = (array) $modules;
 
$return = TRUE;
 
$enabled_modules = array();
 
$t = get_t();
 
// Check to see if each module is enabled.
 
foreach ($modules as $module) {
    if (!
module_exists($module)) {
     
// This module is not enabled, throw an exception.
     
throw new DrupalUpdateException($t('The module @module was supposed to be enabled by this update, but was not. Please investigate the problem and re-run this update.',array('@module' => $module)));
    }
  }
 
$module_list = implode(', ', $modules);

  return $t('The modules @enabled were enabled successfully.', array('@enabled' => $module_list));
}

/**
 * Enables an array of modules and checks to make sure they were truly enabled.
 *
 * @param array $modules
 *   An array of module machine names to check for being enabled.
 *
 * @return string
 *   Messsage indicating the modules are enabled.
 *
 * @throws DrupalUpdateException
 *   Calls the update a failure, preventing it from registering the update_N.
 */
function mymodule_module_enable($modules = array()) {
 
$modules = (array) $modules;
 
$enable_good = module_enable($modules);
  if (!
$enable_good) {
   
// Enable command failed.
   
$module_list = implode(', ', $modules);
   
$t = get_t();
    throw new
DrupalUpdateException($t('The requested modules @modules to be enabled by this update, were not, because one of them does not exist in the codebase. Please investigate the problem and re-run this update.',array('@modules' => $module_list)));
  }
 
// There are cases where $enable_good is TRUE but the module may not have enabled, so double check.
 
$success = mymodule_check_modules_enabled($modules);

  return $success;
}
?>

section:

Comments

swirt's picture

A handy way to figure out what number N a site is at is to use :

drush sqlq "SELECT schema_version from system where name = 'my_module';"
swirt's picture

After doing a bunch of these, I built a better solution. A set of tools for handling deployment through update hooks.
https://www.drupal.org/project/hook_update_deploy_tools