Security update for Core, with self-updated composer
[yaffs-website] / web / core / lib / Drupal / Core / Config / ConfigManager.php
index 65da2e9136d96908725cf880bd9d65975f8dc0c3..e76668306950fe6082e820a697c6c3bcc071daee 100644 (file)
@@ -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]
       );
     }