diff core/lib/Drupal/Core/Config/ConfigManager.php @ 12:7a779792577d

Update Drupal core to v8.4.5 (via Composer)
author Chris Cannam
date Fri, 23 Feb 2018 15:52:07 +0000
parents 4c8ae668cc8c
children af1871eacc83
line wrap: on
line diff
--- a/core/lib/Drupal/Core/Config/ConfigManager.php	Fri Feb 23 15:51:18 2018 +0000
+++ b/core/lib/Drupal/Core/Config/ConfigManager.php	Fri Feb 23 15:52:07 2018 +0000
@@ -292,78 +292,85 @@
    * {@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;