Snippets

Daniel Sasser Drupal 8 Features Revert Programatically

Created by Daniel Sasser
/**
 * Revert or import a feature
 */
function cu_core_revert($args, $force = TRUE) {
  if (!\Drupal::moduleHandler()->moduleExists('features')) {
    throw new Exception('Features is not enabled.');
  }
  /** @var \Drupal\features\FeaturesAssignerInterface $assigner */
  $assigner = \Drupal::service('features_assigner');
  $assigner->assignConfigPackages();

  /** @var \Drupal\features\FeaturesManagerInterface $manager */
  $manager = \Drupal::service('features.manager');
  /** @var \Drupal\config_update\ConfigRevertInterface $config_revert */
  $config_revert = \Drupal::service('features.config_update');

  // Parse list of arguments.
  $modules = array();
  foreach ($args as $arg) {
    $arg = explode(':', $arg);
    $module = array_shift($arg);
    $component = array_shift($arg);

    if (isset($module)) {
      if (empty($component)) {
        // If we received just a feature name, this means that we need all of
        // its components.
        $modules[$module] = TRUE;
      }
      elseif ($modules[$module] !== TRUE) {
        if (!isset($modules[$module])) {
          $modules[$module] = array();
        }
        $modules[$module][] = $component;
      }
    }
  }

  // Process modules.
  foreach ($modules as $module => $components_needed) {

    $dt_args['@module'] = $module;
    /** @var \Drupal\features\Package $feature */
    $feature = $manager->getPackage($module);
    if (!isset($feature)) {
      // See if this is a non-features module.
      $module_handler = \Drupal::moduleHandler();
      $modules = $module_handler->getModuleList();
      if (!empty($modules[$module])) {
        $extension = $modules[$module];
        $feature = $manager->initPackageFromExtension($extension);
        $config = $manager->listExtensionConfig($extension);
        $feature->setConfig($config);
        $feature->setStatus(FeaturesManagerInterface::STATUS_INSTALLED);
      }
    }
    if (empty($feature)) {
      watchdog(t('No such feature is available: @module', $dt_args), 'error');
      return;
    }

    if ($feature->getStatus() != FeaturesManagerInterface::STATUS_INSTALLED) {
      \Drupal::logger('cu_core')->error(t('No such feature is installed: @module', $dt_args));
      return;
    }

    // Forcefully revert all components of a feature.
    if ($force) {
      $components = $feature->getConfigOrig();
    }
    // Only revert components that are detected to be Overridden.
    else {
      $components = $manager->detectOverrides($feature);
      $missing = $manager->reorderMissing($manager->detectMissing($feature));
      // Be sure to import missing components first.
      $components = array_merge($missing, $components);
    }

    if (!empty($components_needed) && is_array($components_needed)) {
      $components = array_intersect($components, $components_needed);
    }

    if (empty($components)) {
      \Drupal::logger('cu_core')->notice(t('Current state already matches active config, aborting.'));
    }
    else {
      $config = $manager->getConfigCollection();
      foreach ($components as $component) {
        $dt_args['@component'] = $component;
        if (!isset($config[$component])) {
          // Import missing component.
          /** @var array $item */
          $item = $manager->getConfigType($component);
          $type = ConfigurationItem::fromConfigStringToConfigType($item['type']);
          $config_revert->import($type, $item['name_short']);
          \Drupal::logger('cu_core')->notice(t('Import @module : @component.', $dt_args));
        }
        else {
          // Revert existing component.
          /** @var \Drupal\features\ConfigurationItem $item */
          $item = $config[$component];
          $type = ConfigurationItem::fromConfigStringToConfigType($item->getType());
          $config_revert->revert($type, $item->getShortName());
          \Drupal::logger('cu_core')->notice(t('Reverted @module : @component.', $dt_args));
        }
      }
    }
  }
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.