FeaturesAssignmentForwardDependency.php 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. <?php
  2. namespace Drupal\features\Plugin\FeaturesAssignment;
  3. use Drupal\Component\Graph\Graph;
  4. use Drupal\features\FeaturesAssignmentMethodBase;
  5. /**
  6. * Class for assigning configuration to packages based on forward dependencies.
  7. *
  8. * @Plugin(
  9. * id = "forward_dependency",
  10. * weight = 20,
  11. * name = @Translation("Forward dependency"),
  12. * description = @Translation("Add to packages configuration on which items in the package depend."),
  13. * )
  14. */
  15. class FeaturesAssignmentForwardDependency extends FeaturesAssignmentMethodBase {
  16. /**
  17. * {@inheritdoc}
  18. */
  19. public function assignPackages($force = FALSE) {
  20. $config_collection = $this->featuresManager->getConfigCollection();
  21. $ordered = $this->dependencyOrder($config_collection);
  22. foreach ($ordered as $name) {
  23. $item = $config_collection[$name];
  24. if ($item->getPackage()) {
  25. // Already has a package, not our business.
  26. continue;
  27. }
  28. // Find packages of dependent items.
  29. $dependent_packages = [];
  30. foreach ($item->getDependents() as $dependent) {
  31. if (isset($config_collection[$dependent])) {
  32. if ($package = $config_collection[$dependent]->getPackage()) {
  33. $dependent_packages[$package] = $package;
  34. }
  35. }
  36. }
  37. // If zero or multiple packages, we don't know what to do.
  38. if (count($dependent_packages) == 1) {
  39. $package = key($dependent_packages);
  40. $this->featuresManager->assignConfigPackage($package, [$name]);
  41. }
  42. }
  43. }
  44. /**
  45. * Get config items such that each item comes before anything it depends on.
  46. *
  47. * @param \Drupal\features\ConfigurationItem[] $config_collection
  48. * A collection of configuration items.
  49. *
  50. * @return string[]
  51. * The names of configuration items, in dependency order.
  52. */
  53. protected function dependencyOrder($config_collection) {
  54. // Populate a graph.
  55. $graph = [];
  56. foreach ($config_collection as $config) {
  57. $graph[$config->getName()] = [];
  58. foreach ($config->getDependents() as $dependent) {
  59. $graph[$config->getName()]['edges'][$dependent] = 1;
  60. }
  61. }
  62. $graph_object = new Graph($graph);
  63. $graph = $graph_object->searchAndSort();
  64. // Order by inverse weight.
  65. $weights = array_column($graph, 'weight');
  66. array_multisort($weights, SORT_DESC, $graph);
  67. return array_keys($graph);
  68. }
  69. }