X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;ds=sidebyside;f=web%2Fcore%2Flib%2FDrupal%2FCore%2FConfig%2FConfigManager.php;fp=web%2Fcore%2Flib%2FDrupal%2FCore%2FConfig%2FConfigManager.php;h=e76668306950fe6082e820a697c6c3bcc071daee;hb=9917807b03b64faf00f6a1f29dcb6eafc454efa5;hp=65da2e9136d96908725cf880bd9d65975f8dc0c3;hpb=aea91e65e895364e460983b890e295aa5d5540a5;p=yaffs-website diff --git a/web/core/lib/Drupal/Core/Config/ConfigManager.php b/web/core/lib/Drupal/Core/Config/ConfigManager.php index 65da2e913..e76668306 100644 --- a/web/core/lib/Drupal/Core/Config/ConfigManager.php +++ b/web/core/lib/Drupal/Core/Config/ConfigManager.php @@ -233,7 +233,7 @@ class ConfigManager implements ConfigManagerInterface { // dependencies on the config entity classes. Assume data with UUID is a // config entity. Only configuration entities can be depended on so we can // ignore everything else. - $data = array_map(function($config) { + $data = array_map(function ($config) { $data = $config->get(); if (isset($data['uuid'])) { return $data; @@ -292,78 +292,85 @@ class ConfigManager implements ConfigManagerInterface { * {@inheritdoc} */ public function getConfigEntitiesToChangeOnDependencyRemoval($type, array $names, $dry_run = TRUE) { - // Determine the current list of dependent configuration entities and set up - // initial values. $dependency_manager = $this->getConfigDependencyManager(); - $dependents = $this->findConfigEntityDependentsAsEntities($type, $names, $dependency_manager); - $original_dependencies = $dependents; - $delete_uuids = []; + // Store the list of dependents in three separate variables. This allows us + // to determine how the dependency graph changes as entities are fixed by + // calling the onDependencyRemoval() method. + + // The list of original dependents on $names. This list never changes. + $original_dependents = $this->findConfigEntityDependentsAsEntities($type, $names, $dependency_manager); + + // The current list of dependents on $names. This list is recalculated when + // calling an entity's onDependencyRemoval() method results in the entity + // changing. This list is passed to each entity's onDependencyRemoval() + // method as the list of affected entities. + $current_dependents = $original_dependents; + + // The list of dependents to process. This list changes as entities are + // processed and are either fixed or deleted. + $dependents_to_process = $original_dependents; + + // Initialize other variables. + $affected_uuids = []; $return = [ 'update' => [], 'delete' => [], 'unchanged' => [], ]; - // Create a map of UUIDs to $original_dependencies key so that we can remove - // fixed dependencies. - $uuid_map = []; - foreach ($original_dependencies as $key => $entity) { - $uuid_map[$entity->uuid()] = $key; - } - - // Try to fix any dependencies and find out what will happen to the - // dependency graph. Entities are processed in the order of most dependent - // first. For example, this ensures that Menu UI third party dependencies on - // node types are fixed before processing the node type's other - // dependencies. - while ($dependent = array_pop($dependents)) { + // Try to fix the dependents and find out what will happen to the dependency + // graph. Entities are processed in the order of most dependent first. For + // example, this ensures that Menu UI third party dependencies on node types + // are fixed before processing the node type's other dependents. + while ($dependent = array_pop($dependents_to_process)) { /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $dependent */ if ($dry_run) { // Clone the entity so any changes do not change any static caches. $dependent = clone $dependent; } $fixed = FALSE; - if ($this->callOnDependencyRemoval($dependent, $original_dependencies, $type, $names)) { + if ($this->callOnDependencyRemoval($dependent, $current_dependents, $type, $names)) { // Recalculate dependencies and update the dependency graph data. $dependent->calculateDependencies(); $dependency_manager->updateData($dependent->getConfigDependencyName(), $dependent->getDependencies()); - // Based on the updated data rebuild the list of dependents. This will - // remove entities that are no longer dependent after the recalculation. - $dependents = $this->findConfigEntityDependentsAsEntities($type, $names, $dependency_manager); - // Remove any entities that we've already marked for deletion. - $dependents = array_filter($dependents, function ($dependent) use ($delete_uuids) { - return !in_array($dependent->uuid(), $delete_uuids); + // Based on the updated data rebuild the list of current dependents. + // This will remove entities that are no longer dependent after the + // recalculation. + $current_dependents = $this->findConfigEntityDependentsAsEntities($type, $names, $dependency_manager); + // Rebuild the list of entities that we need to process using the new + // list of current dependents and removing any entities that we've + // already processed. + $dependents_to_process = array_filter($current_dependents, function ($current_dependent) use ($affected_uuids) { + return !in_array($current_dependent->uuid(), $affected_uuids); }); - // Ensure that the dependency has actually been fixed. It is possible - // that the dependent has multiple dependencies that cause it to be in - // the dependency chain. + // Ensure that the dependent has actually been fixed. It is possible + // that other dependencies cause it to still be in the list. $fixed = TRUE; - foreach ($dependents as $key => $entity) { + foreach ($dependents_to_process as $key => $entity) { if ($entity->uuid() == $dependent->uuid()) { $fixed = FALSE; - unset($dependents[$key]); + unset($dependents_to_process[$key]); break; } } if ($fixed) { - // Remove the fixed dependency from the list of original dependencies. - unset($original_dependencies[$uuid_map[$dependent->uuid()]]); + $affected_uuids[] = $dependent->uuid(); $return['update'][] = $dependent; } } // If the entity cannot be fixed then it has to be deleted. if (!$fixed) { - $delete_uuids[] = $dependent->uuid(); + $affected_uuids[] = $dependent->uuid(); // Deletes should occur in the order of the least dependent first. For // example, this ensures that fields are removed before field storages. array_unshift($return['delete'], $dependent); } } - // Use the lists of UUIDs to filter the original list to work out which - // configuration entities are unchanged. - $return['unchanged'] = array_filter($original_dependencies, function ($dependent) use ($delete_uuids) { - return !(in_array($dependent->uuid(), $delete_uuids)); + // Use the list of affected UUIDs to filter the original list to work out + // which configuration entities are unchanged. + $return['unchanged'] = array_filter($original_dependents, function ($dependent) use ($affected_uuids) { + return !(in_array($dependent->uuid(), $affected_uuids)); }); return $return; @@ -452,7 +459,9 @@ class ConfigManager implements ConfigManagerInterface { // Key the entity arrays by config dependency name to make searching easy. foreach (['config', 'content'] as $dependency_type) { $affected_dependencies[$dependency_type] = array_combine( - array_map(function ($entity) { return $entity->getConfigDependencyName(); }, $affected_dependencies[$dependency_type]), + array_map(function ($entity) { + return $entity->getConfigDependencyName(); + }, $affected_dependencies[$dependency_type]), $affected_dependencies[$dependency_type] ); }