You are here

public function ConfigSplitManager::splitPreview in Configuration Split 2.0.x

Split the config of a split to the preview storage.

Parameters

\Drupal\Core\Config\ImmutableConfig $config: The split config.

\Drupal\Core\Config\StorageInterface $transforming: The transforming storage.

\Drupal\Core\Config\StorageInterface $splitStorage: The splits preview storage.

3 calls to ConfigSplitManager::splitPreview()
ConfigSplitManager::exportTransform in src/ConfigSplitManager.php
Process the export of a split.
ConfigSplitManager::singleDeactivate in src/ConfigSplitManager.php
Deactivate a split.
ConfigSplitManager::singleExportPreview in src/ConfigSplitManager.php
Get the single export preview.

File

src/ConfigSplitManager.php, line 241

Class

ConfigSplitManager
The manager to split and merge.

Namespace

Drupal\config_split

Code

public function splitPreview(ImmutableConfig $config, StorageInterface $transforming, StorageInterface $splitStorage) : void {

  // Empty the split storage.
  foreach (array_merge([
    StorageInterface::DEFAULT_COLLECTION,
  ], $splitStorage
    ->getAllCollectionNames()) as $collection) {
    $splitStorage
      ->createCollection($collection)
      ->deleteAll();
  }
  $transforming = $transforming
    ->createCollection(StorageInterface::DEFAULT_COLLECTION);
  $splitStorage = $splitStorage
    ->createCollection(StorageInterface::DEFAULT_COLLECTION);
  $modules = array_keys($config
    ->get('module'));
  $changes = $this->manager
    ->getConfigEntitiesToChangeOnDependencyRemoval('module', $modules, FALSE);
  $this
    ->processEntitiesToChangeOnDependencyRemoval($changes, $transforming, $splitStorage);
  $completelySplit = array_map(function (ConfigEntityInterface $entity) {
    return $entity
      ->getConfigDependencyName();
  }, $changes['delete']);

  // Process all simple config objects which implicitly depend on modules.
  foreach ($modules as $module) {
    $keys = $this->active
      ->listAll($module . '.');
    $keys = array_diff($keys, $completelySplit);
    foreach ($keys as $name) {
      $splitStorage
        ->write($name, $this->active
        ->read($name));
      $transforming
        ->delete($name);
      $completelySplit[] = $name;
    }
  }

  // Get explicitly split config.
  $completeSplitList = $config
    ->get('complete_list');
  if (!empty($completeSplitList)) {

    // For the complete split we use the active storage config. This way two
    // splits can split the same config and both will have them. But also
    // because we use the config manager service to get entities to change
    // based on the modules which are configured to be split.
    $completeList = array_filter($this->active
      ->listAll(), function ($name) use ($completeSplitList) {

      // Check for wildcards.
      return self::inFilterList($name, $completeSplitList);
    });

    // Check what is not processed already.
    $completeList = array_diff($completeList, $completelySplit);

    // Process also the config being removed.
    $changes = $this->manager
      ->getConfigEntitiesToChangeOnDependencyRemoval('config', $completeList, FALSE);
    $this
      ->processEntitiesToChangeOnDependencyRemoval($changes, $transforming, $splitStorage);

    // Split all the config which was specified but not processed yet.
    $processed = array_map(function (ConfigEntityInterface $entity) {
      return $entity
        ->getConfigDependencyName();
    }, $changes['delete']);
    $unprocessed = array_diff($completeList, $processed);
    foreach ($unprocessed as $name) {
      $splitStorage
        ->write($name, $this->active
        ->read($name));
      $transforming
        ->delete($name);
    }
  }

  // Split from collections what was split from the default collection.
  if (!empty($completelySplit) || !empty($completeSplitList)) {
    foreach ($this->active
      ->getAllCollectionNames() as $collection) {
      $storageCollection = $transforming
        ->createCollection($collection);
      $splitCollection = $splitStorage
        ->createCollection($collection);
      $activeCollection = $this->active
        ->createCollection($collection);
      $removeList = array_filter($activeCollection
        ->listAll(), function ($name) use ($completeSplitList, $completelySplit) {

        // Check for wildcards.
        return in_array($name, $completelySplit) || self::inFilterList($name, $completeSplitList);
      });
      foreach ($removeList as $name) {

        // Split collections.
        $splitCollection
          ->write($name, $activeCollection
          ->read($name));
        $storageCollection
          ->delete($name);
      }
    }
  }

  // Process partial config.
  $partialSplitList = $config
    ->get('partial_list');
  if (!empty($partialSplitList)) {
    foreach (array_merge([
      StorageInterface::DEFAULT_COLLECTION,
    ], $transforming
      ->getAllCollectionNames()) as $collection) {
      $syncCollection = $this->sync
        ->createCollection($collection);
      $activeCollection = $this->active
        ->createCollection($collection);
      $storageCollection = $transforming
        ->createCollection($collection);
      $splitCollection = $splitStorage
        ->createCollection($collection);
      $partialList = array_filter($activeCollection
        ->listAll(), function ($name) use ($partialSplitList, $completelySplit) {

        // Check for wildcards. But skip config which is already split.
        return !in_array($name, $completelySplit) && self::inFilterList($name, $partialSplitList);
      });
      foreach ($partialList as $name) {
        if ($syncCollection
          ->exists($name)) {
          $sync = $syncCollection
            ->read($name);
          $active = $activeCollection
            ->read($name);

          // If the split storage already contains a patch for the config
          // we need to apply it to the sync config so that the updated patch
          // contains both changes. We don't want to undo removing of things
          // that need to be removed due to a module which was split off.
          if ($splitCollection
            ->exists(self::SPLIT_PARTIAL_PREFIX . $name)) {
            $patch = ConfigPatch::fromArray($splitCollection
              ->read(self::SPLIT_PARTIAL_PREFIX . $name));
            $sync = $this->patchMerge
              ->mergePatch($sync, $patch, $name);
          }
          $diff = $this->patchMerge
            ->createPatch($active, $sync);

          // If the diff is empty then sync already contains the data.
          if (!$diff
            ->isEmpty()) {
            $splitCollection
              ->write(self::SPLIT_PARTIAL_PREFIX . $name, $diff
              ->toArray());
            $storageCollection
              ->write($name, $sync);
          }
        }
        else {

          // Split the config completely if it was not in the sync storage.
          $splitCollection
            ->write($name, $activeCollection
            ->read($name));
          $storageCollection
            ->delete($name);
          if ($splitStorage
            ->exists(self::SPLIT_PARTIAL_PREFIX . $name)) {

            // We completely split the config if it doesn't exist in the sync
            // storage, so we can also remove the patch if it exists.
            $splitStorage
              ->delete(self::SPLIT_PARTIAL_PREFIX . $name);
          }
        }
      }
    }
  }

  // Now special case the extensions.
  $extensions = $transforming
    ->read('core.extension');
  if ($extensions === FALSE) {
    return;
  }

  // Split off the extensions.
  $extensions['module'] = array_diff_key($extensions['module'], $config
    ->get('module') ?? []);
  $extensions['theme'] = array_diff_key($extensions['theme'], $config
    ->get('theme') ?? []);
  $transforming
    ->write('core.extension', $extensions);
}