Last Updated: February 25, 2016
·
551
· pbuyle

Feature Revert All in a hook_update_N

I usually revert feautres using the drush feature-revert of drush feature-revert-all commands after running database updates (using drush updatedb). But sometimes, you need to ensure Feautres are reverted before running some database updates, and sometimes you need to revert all the feautres. Off course, if the hook_update_N that needs to run after the features revert are from a different module you will need an hook_update_dependencies implementation.

function MODULE_update_N(&$sandbox) {
  module_load_include('inc', 'features', 'features.export');
  $messages = array();
  if (!isset($sandbox['features_to_revert'])) {
    $sandbox['features_to_revert'] = array();
    foreach (features_get_features(NULL, TRUE) as $module) {
      if ($module->status) {
        $sandbox['features_to_revert'][] = $module->name;
      }
    }
    $sandbox['revered_features'] = array();
  }
  if ($sandbox['features_to_revert']) {
    $module = array_shift($sandbox['features_to_revert']);
    $dt_args['@module'] = $module;
    if (($feature = features_load_feature($module, TRUE)) && module_exists($module)) {
      $components = array();
      // Forcefully revert all components of a feature.
      foreach (array_keys($feature->info['features']) as $component) {
        if (features_hook($component, 'features_revert')) {
          $components[] = $component;
        }
      }
      foreach ($components as $component) {
        $dt_args['@component'] = $component;
        if (features_feature_is_locked($module, $component)) {
          $messages[] = format_string('Skipping locked @module.@component.', $dt_args);
        }
        else {
          features_revert(array($module => array($component)));
          $messages[] = format_string('Reverted @module.@component.', $dt_args);
        }
      }
    }
    $sandbox['revered_features'] = $module;
    if ($sandbox['features_to_revert']) {
      $sandbox['#finished'] = count($sandbox['revered_features']) / (count($sandbox['features_to_revert']) + count($sandbox['revered_features']));
    }
    else {
      $sandbox['#finished'] = 1;
      drupal_flush_all_caches();
    }
  }
  return implode("\n", $messages);
}