Programmatically execute a drush command in an update hook.

September 20, 2017

Submitted by twfahey on Wed, 09/20/2017 - 13:10

Something pretty awesome that I did recently was to figure out how to execute a drush command in an update hook. I was working on a client site in which, we had the dreaded "Missing module" issue - a ton of these harmless yet super annoying warnings whenever a cache-clear or other certain actions were performed:

The following module is missing from the file system: <em              [warning]
class="placeholder">energy_institute_site_configuration</em>. For
information about how to fix this, see <a
href="https://www.drupal.org/node/2487215">the documentation
page</a>. bootstrap.inc:1168
The following module is missing from the file system: <em              [warning]
class="placeholder">slick_homepage_slideshow</em>. For information
about how to fix this, see <a
href="https://www.drupal.org/node/2487215">the documentation
page</a>. bootstrap.inc:1168

...

Of course, "There's a module for that!", https://www.drupal.org/project/module_missing_message_fixer, and it comes with a great drush command for knocking out all those errors in one shot:

drush mmmff --all

So, at first, I thought I could just add the module to my repo, run drush enable and drush mmmff, and call it a day. But what fun is that? Why not demonstrate the ability to do this programmatically, through an update hook within my already enabled deploy module. My Pantheon server was configured to run drush, as was my local environment, so to pull this off, I had to combine a couple of drush functions:

/**
 * Get rid of pesky missing module warnings.
 */
function mymodule_deploy_update_7101(&$sandbox) {
  $modules_to_enable = array(
    'module_missing_message_fixer'
  );
  module_enable($modules_to_enable);
  drush_print("Enabled module_missing_message_fixer. Executing fix...");
  drush_set_option('all', 'all');
  drush_invoke('module-missing-message-fixer-fix');
}

At first, I was trying just the drush_invoke, but it was complaining that I hadn't passed '--all'. After a bit of research, I realized it's possible to use drush_set_option to simulate the passing of that type of argument from the command line. I can also note here that drush_invoke takes an array as a second argument if you need to pass the name of a specific module in this case, but whatever kind of command line argument that might be expected to be passed if you were trying to simulate something like:

drush mmmff some_module_name

So in that case, I believe you could modify the update slightly:

/**
 * Get rid of pesky missing module for a specific module.
 */
function mymodule_deploy_update_7101(&$sandbox) {
  $modules_to_enable = array(
    'module_missing_message_fixer'
  );
  module_enable($modules_to_enable);
  drush_print("Enabled module_missing_message_fixer. Executing fix...");
  drush_invoke('module-missing-message-fixer-fix', array(
   'some_module_name',
  ));
}

 

Many thanks to http://www.drupalcontrib.org/, I referenced them through the process.