diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index e46ba1463..c6f5325d3 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -117,8 +117,6 @@ EOF; // flatten array $classMap = array(); - $autoloads['classmap'] = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($autoloads['classmap'])); - if ($scanPsr0Packages) { foreach ($autoloads['psr-0'] as $namespace => $paths) { foreach ($paths as $dir) { @@ -139,6 +137,8 @@ EOF; } } } + + $autoloads['classmap'] = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($autoloads['classmap'])); foreach ($autoloads['classmap'] as $dir) { foreach (ClassMapGenerator::createMap($dir) as $class => $path) { $path = '/'.$filesystem->findShortestPath(getcwd(), $path, true); @@ -170,28 +170,13 @@ EOF; { // build package => install path map $packageMap = array(); - $packages[] = $mainPackage; - - // sort packages by dependencies - usort($packages, function (PackageInterface $a, PackageInterface $b) { - foreach (array_merge($a->getRequires(), $a->getDevRequires()) as $link) { - if (in_array($link->getTarget(), $b->getNames())) { - return 1; - } - } - foreach (array_merge($b->getRequires(), $b->getDevRequires()) as $link) { - if (in_array($link->getTarget(), $a->getNames())) { - return -1; - } - } - - return strcmp($a->getName(), $b->getName()); - }); + array_unshift($packages, $mainPackage); foreach ($packages as $package) { if ($package instanceof AliasPackage) { continue; } + if ($package === $mainPackage) { $packageMap[] = array($mainPackage, ''); continue; @@ -213,32 +198,12 @@ EOF; */ public function parseAutoloads(array $packageMap) { - $autoloads = array('classmap' => array(), 'psr-0' => array(), 'files' => array()); - foreach ($packageMap as $item) { - list($package, $installPath) = $item; + $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0'); + krsort($psr0); + $classmap = $this->parseAutoloadsType($packageMap, 'classmap'); + $files = $this->parseAutoloadsType($this->sortPackageMap($packageMap), 'files'); - if (null !== $package->getTargetDir()) { - $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir())); - } - - foreach ($package->getAutoload() as $type => $mapping) { - // skip misconfigured packages - if (!is_array($mapping)) { - continue; - } - - foreach ($mapping as $namespace => $paths) { - foreach ((array) $paths as $path) { - $autoloads[$type][$namespace][] = empty($installPath) ? $path : $installPath.'/'.$path; - } - } - } - } - - krsort($autoloads['classmap']); - krsort($autoloads['psr-0']); - - return $autoloads; + return array('psr-0' => $psr0, 'classmap' => $classmap, 'files' => $files); } /** @@ -445,4 +410,68 @@ FOOTER; } + protected function parseAutoloadsType(array $packageMap, $type) + { + $autoloads = array(); + foreach ($packageMap as $item) { + list($package, $installPath) = $item; + + $autoload = $package->getAutoload(); + // skip misconfigured packages + if (!isset($autoload[$type]) || !is_array($autoload[$type])) { + continue; + } + + if (null !== $package->getTargetDir()) { + $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir())); + } + + foreach ($autoload[$type] as $namespace => $paths) { + foreach ((array) $paths as $path) { + $autoloads[$namespace][] = empty($installPath) ? $path : $installPath.'/'.$path; + } + } + } + + return $autoloads; + } + + protected function sortPackageMap(array $packageMap) + { + $groups = array(); + $names = array(); + foreach ($packageMap as $key => $item) { + $groups[$key] = array($item); + $mainName = $item[0]->getName(); + foreach ($item[0]->getNames() as $name) { + $names[$name] = $name == $mainName ? $key : $mainName; + } + } + + foreach ($packageMap as $item) { + foreach (array_merge($item[0]->getRequires(), $item[0]->getDevRequires()) as $link) { + if (!isset($names[$link->getTarget()])) { + continue; + } + + $packageKey = $names[$item[0]->getName()]; + $target = $link->getTarget(); + $targetKey = is_int($names[$target]) ? $names[$target] : $names[$names[$target]]; + $groups[$targetKey] = array_merge($groups[$targetKey], $groups[$packageKey]); + + foreach ($groups[$packageKey] as $originalItem) { + $names[$originalItem[0]->getName()] = $targetKey; + } + + unset($groups[$packageKey]); + } + } + + $sortedPackageMap = array(); + foreach ($groups as $group) { + $sortedPackageMap = array_merge($sortedPackageMap, $group); + } + + return $sortedPackageMap; + } }