Skip to content
Snippets Groups Projects

Issue #3514034: Do not completely split items depending on patched ones

+ 56
0
@@ -314,6 +314,7 @@ public function splitPreview(ImmutableConfig $config, StorageInterface $transfor
$modules = array_keys($config->get('module'));
$changes = $this->manager->getConfigEntitiesToChangeOnDependencyRemoval('module', $modules, TRUE);
$changes = $this->reprocessDeletions($changes);
$this->processEntitiesToChangeOnDependencyRemoval($changes, $source, $transforming, $splitStorage);
$completelySplit = array_map(function (ConfigEntityInterface $entity) {
@@ -346,6 +347,7 @@ public function splitPreview(ImmutableConfig $config, StorageInterface $transfor
// Process also the config being removed.
$changes = $this->manager->getConfigEntitiesToChangeOnDependencyRemoval('config', $completeList, TRUE);
$changes = $this->reprocessDeletions($changes, $completeSplitList);
$this->processEntitiesToChangeOnDependencyRemoval($changes, $source, $transforming, $splitStorage);
// Split all the config which was specified but not processed yet.
@@ -423,6 +425,60 @@ public function splitPreview(ImmutableConfig $config, StorageInterface $transfor
$transforming->write('core.extension', $extensions);
}
/**
* Reprocesses changes to include only actual deletions.
*
* To compute items needing patching, config items are flagged as being
* removed: this may cause config items depending on those to be flagged as
* needing removal as well, whereas they may actually be unaffected. This
* recalculates dependencies for items flagged for removal to confirm it is
* actually required.
*
* @param string[][] $changes
* An associative array keyed by change type of config item name arrays.
* @param string[] $legit_deletions
* (optional) An array of config item names which should legitimately be
* deleted.
*
* @return string[][]
* The reprocessed changes array.
*/
protected function reprocessDeletions(array $changes, array $legit_deletions = []): array {
if (!$changes['delete']) {
return $changes;
}
// Collect updated configuration dependencies and check whether any of them
// is a dependency of items flagged for removal, in which case the latter
// need to be double-checked.
$key_array = fn (array $array) => array_combine(array_map(fn (ConfigEntityInterface $entity) => $entity->getConfigDependencyName(), $array), $array);
$deleted_config = $key_array($changes['delete']);
$updated_config = $key_array($changes['update']);
$updated_dependencies = $this->manager->findConfigEntityDependencies('config', array_keys($updated_config));
$actually_deleted_config = array_merge(array_diff_key($deleted_config, $updated_dependencies), array_flip($legit_deletions));
$actually_updated_config = array_diff_key($deleted_config, $actually_deleted_config);
// Collect dependencies of the config items being re-evaluated to confirm
// none of them is flagged for removal.
$actually_updated_dependencies = [];
foreach (array_map(fn (ConfigEntityInterface $entity) => $entity->getDependencies(), $actually_updated_config) as $dependency) {
if (!empty($dependency['config'])) {
$actually_updated_dependencies += array_flip($dependency['config']);
}
}
$actually_deleted_config = array_diff_key($actually_deleted_config, $actually_updated_dependencies);
// Update the list of legit config item updates and deletions based on the
// findings above.
$actually_updated_config = array_diff_key($deleted_config, $actually_deleted_config);
if ($actually_updated_config) {
$changes['update'] = array_values($updated_config + $actually_updated_config);
$changes['delete'] = array_values(array_intersect_key($deleted_config, $actually_deleted_config));
}
return $changes;
}
/**
* Merge the config of a split to the transformation storage.
*
Loading