comparison 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
comparison
equal deleted inserted replaced
11:bfffd8d7479a 12:7a779792577d
290 290
291 /** 291 /**
292 * {@inheritdoc} 292 * {@inheritdoc}
293 */ 293 */
294 public function getConfigEntitiesToChangeOnDependencyRemoval($type, array $names, $dry_run = TRUE) { 294 public function getConfigEntitiesToChangeOnDependencyRemoval($type, array $names, $dry_run = TRUE) {
295 // Determine the current list of dependent configuration entities and set up
296 // initial values.
297 $dependency_manager = $this->getConfigDependencyManager(); 295 $dependency_manager = $this->getConfigDependencyManager();
298 $dependents = $this->findConfigEntityDependentsAsEntities($type, $names, $dependency_manager); 296
299 $original_dependencies = $dependents; 297 // Store the list of dependents in three separate variables. This allows us
300 $delete_uuids = []; 298 // to determine how the dependency graph changes as entities are fixed by
301 299 // calling the onDependencyRemoval() method.
300
301 // The list of original dependents on $names. This list never changes.
302 $original_dependents = $this->findConfigEntityDependentsAsEntities($type, $names, $dependency_manager);
303
304 // The current list of dependents on $names. This list is recalculated when
305 // calling an entity's onDependencyRemoval() method results in the entity
306 // changing. This list is passed to each entity's onDependencyRemoval()
307 // method as the list of affected entities.
308 $current_dependents = $original_dependents;
309
310 // The list of dependents to process. This list changes as entities are
311 // processed and are either fixed or deleted.
312 $dependents_to_process = $original_dependents;
313
314 // Initialize other variables.
315 $affected_uuids = [];
302 $return = [ 316 $return = [
303 'update' => [], 317 'update' => [],
304 'delete' => [], 318 'delete' => [],
305 'unchanged' => [], 319 'unchanged' => [],
306 ]; 320 ];
307 321
308 // Create a map of UUIDs to $original_dependencies key so that we can remove 322 // Try to fix the dependents and find out what will happen to the dependency
309 // fixed dependencies. 323 // graph. Entities are processed in the order of most dependent first. For
310 $uuid_map = []; 324 // example, this ensures that Menu UI third party dependencies on node types
311 foreach ($original_dependencies as $key => $entity) { 325 // are fixed before processing the node type's other dependents.
312 $uuid_map[$entity->uuid()] = $key; 326 while ($dependent = array_pop($dependents_to_process)) {
313 }
314
315 // Try to fix any dependencies and find out what will happen to the
316 // dependency graph. Entities are processed in the order of most dependent
317 // first. For example, this ensures that Menu UI third party dependencies on
318 // node types are fixed before processing the node type's other
319 // dependencies.
320 while ($dependent = array_pop($dependents)) {
321 /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $dependent */ 327 /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $dependent */
322 if ($dry_run) { 328 if ($dry_run) {
323 // Clone the entity so any changes do not change any static caches. 329 // Clone the entity so any changes do not change any static caches.
324 $dependent = clone $dependent; 330 $dependent = clone $dependent;
325 } 331 }
326 $fixed = FALSE; 332 $fixed = FALSE;
327 if ($this->callOnDependencyRemoval($dependent, $original_dependencies, $type, $names)) { 333 if ($this->callOnDependencyRemoval($dependent, $current_dependents, $type, $names)) {
328 // Recalculate dependencies and update the dependency graph data. 334 // Recalculate dependencies and update the dependency graph data.
329 $dependent->calculateDependencies(); 335 $dependent->calculateDependencies();
330 $dependency_manager->updateData($dependent->getConfigDependencyName(), $dependent->getDependencies()); 336 $dependency_manager->updateData($dependent->getConfigDependencyName(), $dependent->getDependencies());
331 // Based on the updated data rebuild the list of dependents. This will 337 // Based on the updated data rebuild the list of current dependents.
332 // remove entities that are no longer dependent after the recalculation. 338 // This will remove entities that are no longer dependent after the
333 $dependents = $this->findConfigEntityDependentsAsEntities($type, $names, $dependency_manager); 339 // recalculation.
334 // Remove any entities that we've already marked for deletion. 340 $current_dependents = $this->findConfigEntityDependentsAsEntities($type, $names, $dependency_manager);
335 $dependents = array_filter($dependents, function ($dependent) use ($delete_uuids) { 341 // Rebuild the list of entities that we need to process using the new
336 return !in_array($dependent->uuid(), $delete_uuids); 342 // list of current dependents and removing any entities that we've
343 // already processed.
344 $dependents_to_process = array_filter($current_dependents, function ($current_dependent) use ($affected_uuids) {
345 return !in_array($current_dependent->uuid(), $affected_uuids);
337 }); 346 });
338 // Ensure that the dependency has actually been fixed. It is possible 347 // Ensure that the dependent has actually been fixed. It is possible
339 // that the dependent has multiple dependencies that cause it to be in 348 // that other dependencies cause it to still be in the list.
340 // the dependency chain.
341 $fixed = TRUE; 349 $fixed = TRUE;
342 foreach ($dependents as $key => $entity) { 350 foreach ($dependents_to_process as $key => $entity) {
343 if ($entity->uuid() == $dependent->uuid()) { 351 if ($entity->uuid() == $dependent->uuid()) {
344 $fixed = FALSE; 352 $fixed = FALSE;
345 unset($dependents[$key]); 353 unset($dependents_to_process[$key]);
346 break; 354 break;
347 } 355 }
348 } 356 }
349 if ($fixed) { 357 if ($fixed) {
350 // Remove the fixed dependency from the list of original dependencies. 358 $affected_uuids[] = $dependent->uuid();
351 unset($original_dependencies[$uuid_map[$dependent->uuid()]]);
352 $return['update'][] = $dependent; 359 $return['update'][] = $dependent;
353 } 360 }
354 } 361 }
355 // If the entity cannot be fixed then it has to be deleted. 362 // If the entity cannot be fixed then it has to be deleted.
356 if (!$fixed) { 363 if (!$fixed) {
357 $delete_uuids[] = $dependent->uuid(); 364 $affected_uuids[] = $dependent->uuid();
358 // Deletes should occur in the order of the least dependent first. For 365 // Deletes should occur in the order of the least dependent first. For
359 // example, this ensures that fields are removed before field storages. 366 // example, this ensures that fields are removed before field storages.
360 array_unshift($return['delete'], $dependent); 367 array_unshift($return['delete'], $dependent);
361 } 368 }
362 } 369 }
363 // Use the lists of UUIDs to filter the original list to work out which 370 // Use the list of affected UUIDs to filter the original list to work out
364 // configuration entities are unchanged. 371 // which configuration entities are unchanged.
365 $return['unchanged'] = array_filter($original_dependencies, function ($dependent) use ($delete_uuids) { 372 $return['unchanged'] = array_filter($original_dependents, function ($dependent) use ($affected_uuids) {
366 return !(in_array($dependent->uuid(), $delete_uuids)); 373 return !(in_array($dependent->uuid(), $affected_uuids));
367 }); 374 });
368 375
369 return $return; 376 return $return;
370 } 377 }
371 378