diff --git a/core/lib/Drupal/Component/Graph/Graph.php b/core/lib/Drupal/Component/Graph/Graph.php index 8fc7d21..6b84cac 100644 --- a/core/lib/Drupal/Component/Graph/Graph.php +++ b/core/lib/Drupal/Component/Graph/Graph.php @@ -18,6 +18,11 @@ class Graph { protected $graph; /** + * Holds the last visit order, the opposite of a topological sort list. + */ + protected $lastVisited; + + /** * Instantiates the depth first search object. * * @param $graph @@ -78,7 +83,7 @@ public function searchAndSort() { // request, and then every 1 weighted etc. $component_weights = array(); - foreach ($state['last_visit_order'] as $vertex) { + foreach ($this->lastVisited as $vertex) { $component = $this->graph[$vertex]['component']; if (!isset($component_weights[$component])) { $component_weights[$component] = 0; @@ -136,14 +141,12 @@ protected function depthFirstSearch(&$state, $start, &$component = NULL) { unset($state['components'][$component]); $component = $new_component; } - // Only visit existing vertices. - if (isset($this->graph[$end])) { - // Visit the connected vertex. - $this->depthFirstSearch($state, $end, $component); + $this->graph += array($end => array('drain' => TRUE)); + // Visit the connected vertex. + $this->depthFirstSearch($state, $end, $component); - // All vertices reachable by $end are also reachable by $start. - $this->graph[$start]['paths'] += $this->graph[$end]['paths']; - } + // All vertices reachable by $end are also reachable by $start. + $this->graph[$start]['paths'] += $this->graph[$end]['paths']; } } @@ -157,6 +160,26 @@ protected function depthFirstSearch(&$state, $start, &$component = NULL) { // Record the order of the last visit. This is the reverse of the // topological order if the graph is acyclic. - $state['last_visit_order'][] = $start; + $this->lastVisited[] = $start; + } + + /** + * Calculates Topological Sorted List of Vertices. + * + * The list is DepthFirst sorted so we can loop over the result like + * @code + * foreach ($graph->getTopologicalSortedList() as $module) { + * module_enable($module); + * } + * @endcode + * + * @return array + */ + public function getTopologicalSortedList() { + if (!isset($this->lastVisited)) { + $this->searchAndSort(); + } + return $this->lastVisited; } + } diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc index b483e7e..93f5449 100644 --- a/core/modules/system/system.admin.inc +++ b/core/modules/system/system.admin.inc @@ -856,7 +856,7 @@ function system_modules($form, $form_state = array()) { // If this module requires other modules, add them to the array. foreach ($module->requires as $requires => $v) { - if (!isset($files[$requires])) { + if (!empty($files[$requires]['drain'])) { $extra['requires'][$requires] = t('@module (missing)', array('@module' => drupal_ucfirst($requires))); $extra['disabled'] = TRUE; } @@ -1158,7 +1158,7 @@ function system_modules_submit($form, &$form_state) { $dependencies = array(); foreach (array_keys($files[$name]->requires) as $required) { if (empty($modules[$required]['enabled'])) { - if (isset($files[$required])) { + if (empty($files[$required]['drain'])) { $dependencies[] = $files[$required]->info['name']; $modules[$required]['enabled'] = TRUE; }