DependencyChecker.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Module;
  7. use Magento\Framework\Data\Graph;
  8. /**
  9. * Checks for dependencies between modules
  10. */
  11. class DependencyChecker
  12. {
  13. /**
  14. * Enabled module list from configuration
  15. *
  16. * @var array
  17. */
  18. private $enabledModuleList;
  19. /**
  20. * The full module list information from filesystem
  21. *
  22. * @var array
  23. */
  24. private $fullModuleList;
  25. /**
  26. * Graph
  27. *
  28. * @var Graph
  29. */
  30. private $graph;
  31. /**
  32. * @var PackageInfo
  33. */
  34. protected $packageInfo;
  35. /**
  36. * Constructor
  37. *
  38. * @param ModuleList $list
  39. * @param ModuleList\Loader $loader
  40. * @param PackageInfoFactory $packageInfoFactory
  41. */
  42. public function __construct(ModuleList $list, ModuleList\Loader $loader, PackageInfoFactory $packageInfoFactory)
  43. {
  44. $this->enabledModuleList = $list->getNames();
  45. $this->fullModuleList = $loader->load();
  46. $this->packageInfo = $packageInfoFactory->create();
  47. }
  48. /**
  49. * Checks dependencies when disabling modules
  50. *
  51. * @param string[] $toBeDisabledModules
  52. * @param string[] $currentlyEnabledModules
  53. * @return array
  54. */
  55. public function checkDependenciesWhenDisableModules($toBeDisabledModules, $currentlyEnabledModules = null)
  56. {
  57. $masterList = isset($currentlyEnabledModules) ? $currentlyEnabledModules : $this->enabledModuleList;
  58. // assume disable succeeds: currently enabled modules - to-be-disabled modules
  59. $enabledModules = array_diff($masterList, $toBeDisabledModules);
  60. return $this->checkDependencyGraph(false, $toBeDisabledModules, $enabledModules);
  61. }
  62. /**
  63. * Checks dependencies when enabling modules
  64. *
  65. * @param string[] $toBeEnabledModules
  66. * @param string[] $currentlyEnabledModules
  67. * @return array
  68. */
  69. public function checkDependenciesWhenEnableModules($toBeEnabledModules, $currentlyEnabledModules = null)
  70. {
  71. $masterList = isset($currentlyEnabledModules) ? $currentlyEnabledModules : $this->enabledModuleList;
  72. // assume enable succeeds: union of currently enabled modules and to-be-enabled modules
  73. $enabledModules = array_unique(array_merge($masterList, $toBeEnabledModules));
  74. return $this->checkDependencyGraph(true, $toBeEnabledModules, $enabledModules);
  75. }
  76. /**
  77. * Check the dependency graph
  78. *
  79. * @param bool $isEnable
  80. * @param string[] $moduleNames list of modules to be enabled/disabled
  81. * @param string[] $enabledModules list of enabled modules assuming enable/disable succeeds
  82. * @return array
  83. */
  84. private function checkDependencyGraph($isEnable, $moduleNames, $enabledModules)
  85. {
  86. $this->graph = $this->createGraph();
  87. $dependenciesMissingAll = [];
  88. $graphMode = $isEnable ? Graph::DIRECTIONAL : Graph::INVERSE;
  89. foreach ($moduleNames as $moduleName) {
  90. $dependenciesMissing = [];
  91. $paths = $this->graph->findPathsToReachableNodes($moduleName, $graphMode);
  92. $modules = array_merge(
  93. array_keys($this->fullModuleList),
  94. $this->packageInfo->getNonExistingDependencies()
  95. );
  96. foreach ($modules as $module) {
  97. if (isset($paths[$module])) {
  98. if ($isEnable && !in_array($module, $enabledModules)) {
  99. $dependenciesMissing[$module] = $paths[$module];
  100. } elseif (!$isEnable && in_array($module, $enabledModules)) {
  101. $dependenciesMissing[$module] = array_reverse($paths[$module]);
  102. }
  103. }
  104. }
  105. $dependenciesMissingAll[$moduleName] = $dependenciesMissing;
  106. }
  107. return $dependenciesMissingAll;
  108. }
  109. /**
  110. * Create the dependency graph
  111. *
  112. * @return Graph
  113. */
  114. private function createGraph()
  115. {
  116. $nodes = [];
  117. $dependencies = [];
  118. // build the graph data
  119. foreach (array_keys($this->fullModuleList) as $moduleName) {
  120. $nodes[] = $moduleName;
  121. foreach ($this->packageInfo->getRequire($moduleName) as $dependModuleName) {
  122. if ($dependModuleName) {
  123. $dependencies[] = [$moduleName, $dependModuleName];
  124. }
  125. }
  126. }
  127. $nodes = array_unique(
  128. array_merge($nodes, $this->packageInfo->getNonExistingDependencies())
  129. );
  130. return new Graph($nodes, $dependencies);
  131. }
  132. }