diff --git a/core/lib/Drupal/Component/Graph/Graph.php b/core/lib/Drupal/Component/Graph/Graph.php index 8fc7d21..80fcab5 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,7 @@ 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); - - // All vertices reachable by $end are also reachable by $start. - $this->graph[$start]['paths'] += $this->graph[$end]['paths']; - } + $this->visit($state, $end, $component); } } @@ -157,6 +155,30 @@ 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; } + + /** + * Visit a vertex. + * + * @param $state + * An associative array. The key 'last_visit_order' stores a list of the + * vertices visited. The key components stores list of vertices belonging + * to the same the component. + * @param $start + * An arbitrary vertex. + * @param $component + * The component of the last vertex. + */ + protected function visit($state, $vertex, $component) { + // Only visit existing vertices. + if (isset($this->graph[$vertex])) { + // Visit the connected vertex. + $this->depthFirstSearch($state, $vertex, $component); + + // All vertices reachable by $vertex are also reachable by $start. + $this->graph[$start]['paths'] += $this->graph[$vertex]['paths']; + } + } + } diff --git a/core/lib/Drupal/Component/Graph/TopologicalSort.php b/core/lib/Drupal/Component/Graph/TopologicalSort.php new file mode 100644 index 0000000..4e5a5a4 --- /dev/null +++ b/core/lib/Drupal/Component/Graph/TopologicalSort.php @@ -0,0 +1,24 @@ +graph += array($vertex => array()); + parent::visit($state, $vertex, $component); + } + + public function getTopologicalSortedList() { + if (!isset($this->lastVisited)) { + $this->searchAndSort(); + } + return array_reverse($this->lastVisited); + } + +}