[TASK] Observe ext suggestions for ext loading order
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Package / DependencyResolver.php
index 2419e49..77e496e 100644 (file)
@@ -140,6 +140,9 @@ class DependencyResolver {
                // Initialize the dependencies with FALSE
                $dependencyGraph = array_fill_keys($packageKeys, array_fill_keys($packageKeys, FALSE));
                foreach ($packageKeys as $packageKey) {
+                       if (!isset($packageStatesConfiguration[$packageKey]['dependencies'])) {
+                               continue;
+                       }
                        $dependentPackageKeys = $packageStatesConfiguration[$packageKey]['dependencies'];
                        foreach ($dependentPackageKeys as $dependentPackageKey) {
                                if (!in_array($dependentPackageKey, $packageKeys)) {
@@ -151,9 +154,49 @@ class DependencyResolver {
                                $dependencyGraph[$packageKey][$dependentPackageKey] = TRUE;
                        }
                }
+               foreach ($packageKeys as $packageKey) {
+                       if (!isset($packageStatesConfiguration[$packageKey]['suggestions'])) {
+                               continue;
+                       }
+                       $suggestedPackageKeys = $packageStatesConfiguration[$packageKey]['suggestions'];
+                       foreach ($suggestedPackageKeys as $suggestedPackageKey) {
+                               if (!in_array($suggestedPackageKey, $packageKeys)) {
+                                       continue;
+                               }
+                               // Check if there's no dependency of the suggestion to the package
+                               // Dependencies take precedence over suggestions
+                               $dependencies = $this->findPathInGraph($dependencyGraph, $suggestedPackageKey, $packageKey);
+                               if (empty($dependencies)) {
+                                       $dependencyGraph[$packageKey][$suggestedPackageKey] = TRUE;
+                               }
+                       }
+               }
                return $dependencyGraph;
        }
 
+       /**
+        * Find any path in the graph from given start node to destination node
+        *
+        * @param array $graph Directed graph
+        * @param string $from Start node
+        * @param string $to Destination node
+        * @return array Nodes of the found path; empty if no path is found
+        */
+       protected function findPathInGraph(array $graph, $from, $to) {
+               foreach (array_keys(array_filter($graph[$from])) as $node) {
+                       if ($node === $to) {
+                               return array($from, $to);
+                       } else {
+                               $subPath = $this->findPathInGraph($graph, $node, $to);
+                               if (!empty($subPath)) {
+                                       array_unshift($subPath, $from);
+                                       return $subPath;
+                               }
+                       }
+               }
+               return array();
+       }
+
        /**
         * Adds all root packages of current dependency graph as dependency
         * to all extensions.