function ConfigImporter::createExtensionChangelist

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/Config/ConfigImporter.php \Drupal\Core\Config\ConfigImporter::createExtensionChangelist()
  2. 8.9.x core/lib/Drupal/Core/Config/ConfigImporter.php \Drupal\Core\Config\ConfigImporter::createExtensionChangelist()
  3. 11.x core/lib/Drupal/Core/Config/ConfigImporter.php \Drupal\Core\Config\ConfigImporter::createExtensionChangelist()

Populates the extension change list.

1 call to ConfigImporter::createExtensionChangelist()
ConfigImporter::validate in core/lib/Drupal/Core/Config/ConfigImporter.php
Dispatches validate event for a ConfigImporter object.

File

core/lib/Drupal/Core/Config/ConfigImporter.php, line 383

Class

ConfigImporter
Defines a configuration importer.

Namespace

Drupal\Core\Config

Code

protected function createExtensionChangelist() {
  // Create an empty changelist.
  $this->extensionChangelist = $this->getEmptyExtensionsProcessedList();
  // Read the extensions information to determine changes.
  $current_extensions = $this->storageComparer
    ->getTargetStorage()
    ->read('core.extension');
  $new_extensions = $this->storageComparer
    ->getSourceStorage()
    ->read('core.extension');
  // If there is no extension information in sync then exit. This is probably
  // due to an empty sync directory.
  if (!$new_extensions) {
    return;
  }
  // Reset the module list in case a stale cache item has been set by another
  // process during deployment.
  $this->moduleExtensionList
    ->reset();
  // Get a list of modules with dependency weights as values.
  $module_data = $this->moduleExtensionList
    ->getList();
  // Use the actual module weights.
  $module_list = array_combine(array_keys($module_data), array_keys($module_data));
  $module_list = array_map(function ($module) use ($module_data) {
    return $module_data[$module]->sort;
  }, $module_list);
  // Determine which modules to uninstall.
  $uninstall = array_keys(array_diff_key($current_extensions['module'], $new_extensions['module']));
  // Sort the list of newly uninstalled extensions by their weights, so that
  // dependencies are uninstalled last. Extensions of the same weight are
  // sorted in reverse alphabetical order, to ensure the order is exactly
  // opposite from installation. For example, this module list:
  // @code
  // array(
  //   'actions' => 0,
  //   'ban' => 0,
  //   'options' => -2,
  //   'text' => -1,
  // );
  // @endcode
  // Will result in the following sort order:
  // 1. -2   options
  // 2. -1   text
  // 3.  0 0 ban
  // 4.  0 1 actions
  // @todo Move this sorting functionality to the extension system.
  array_multisort(array_values($module_list), SORT_ASC, array_keys($module_list), SORT_DESC, $module_list);
  $this->extensionChangelist['module']['uninstall'] = array_intersect(array_keys($module_list), $uninstall);
  // Determine which modules to install.
  $install = array_keys(array_diff_key($new_extensions['module'], $current_extensions['module']));
  // Always install required modules first. Respect the dependencies between
  // the modules.
  $install_required = [];
  $install_non_required = [];
  foreach ($install as $module) {
    if (!isset($module_data[$module])) {
      // The module doesn't exist. This is handled in
      // \Drupal\Core\EventSubscriber\ConfigImportSubscriber::validateModules().
      continue;
    }
    if (!empty($module_data[$module]->info['required'])) {
      $install_required[$module] = $module_data[$module]->sort;
    }
    else {
      $install_non_required[$module] = $module_data[$module]->sort;
    }
  }
  // Ensure that installed modules are sorted in exactly the reverse order
  // (with dependencies installed first, and modules of the same weight sorted
  // in alphabetical order).
  arsort($install_required);
  arsort($install_non_required);
  $this->extensionChangelist['module']['install'] = array_keys($install_required + $install_non_required);
  // If we're installing the install profile ensure it comes last in the
  // list of modules to be installed. This will occur when installing a site
  // from configuration.
  if (isset($new_extensions['profile'])) {
    $install_profile_key = array_search($new_extensions['profile'], $this->extensionChangelist['module']['install'], TRUE);
    // If the profile is not in the list of modules to be installed this will
    // generate a validation error. See
    // \Drupal\Core\EventSubscriber\ConfigImportSubscriber::validateModules().
    if ($install_profile_key !== FALSE) {
      unset($this->extensionChangelist['module']['install'][$install_profile_key]);
      $this->extensionChangelist['module']['install'][] = $new_extensions['profile'];
    }
  }
  // Get a list of themes with dependency weights as values.
  $theme_data = $this->themeExtensionList
    ->getList();
  // Use the actual theme weights.
  $theme_list = array_combine(array_keys($theme_data), array_keys($theme_data));
  $theme_list = array_map(function ($theme) use ($theme_data) {
    return $theme_data[$theme]->sort;
  }, $theme_list);
  array_multisort(array_values($theme_list), SORT_ASC, array_keys($theme_list), SORT_DESC, $theme_list);
  // Work out what themes to install and to uninstall.
  $uninstall = array_keys(array_diff_key($current_extensions['theme'], $new_extensions['theme']));
  $this->extensionChangelist['theme']['uninstall'] = array_intersect(array_keys($theme_list), $uninstall);
  // Ensure that installed themes are sorted in exactly the reverse order
  // (with dependencies installed first, and themes of the same weight sorted
  // in alphabetical order).
  $install = array_keys(array_diff_key($new_extensions['theme'], $current_extensions['theme']));
  $theme_list = array_reverse($theme_list);
  $this->extensionChangelist['theme']['install'] = array_intersect(array_keys($theme_list), $install);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.