* Jordi Boggiano * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Composer\Autoload; use Composer\Installer\InstallationManager; use Composer\Json\JsonFile; use Composer\Package\Loader\JsonLoader; use Composer\Package\PackageInterface; use Composer\Repository\RepositoryInterface; use Composer\Downloader\Util\Filesystem; /** * @author Igor Wiedler * @author Jordi Boggiano */ class AutoloadGenerator { public function dump(RepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir) { $autoloadFile = <<<'EOF' $path) { $loader->add($namespace, $path); } $loader->register(); return $loader; }; return $__composer_autoload_init(); EOF; $filesystem = new Filesystem(); $vendorPath = strtr(realpath($installationManager->getVendorPath()), '\\', '/'); $relVendorPath = $filesystem->findShortestPath(getcwd(), $vendorPath); $vendorDirCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true); $namespacesFile = << install path map $packageMap = array(); // add main package $packageMap[] = array($mainPackage, ''); foreach ($localRepo->getPackages() as $installedPackage) { $packageMap[] = array( $installedPackage, $installationManager->getInstallPath($installedPackage) ); } $autoloads = $this->parseAutoloads($packageMap); $appBaseDir = $filesystem->findShortestPathCode($vendorPath, getcwd(), true); $appBaseDir = str_replace('__DIR__', '$vendorDir', $appBaseDir); if (isset($autoloads['psr-0'])) { foreach ($autoloads['psr-0'] as $namespace => $paths) { $exportedPaths = array(); foreach ($paths as $path) { $path = strtr($path, '\\', '/'); $baseDir = ''; if (!$filesystem->isAbsolutePath($path)) { // vendor dir == working dir if (preg_match('{^(\./?)?$}', $relVendorPath)) { $path = '/'.$path; $baseDir = '$vendorDir . '; } elseif (strpos($path, $relVendorPath) === 0) { // path starts with vendor dir $path = substr($path, strlen($relVendorPath)); $baseDir = '$vendorDir . '; } else { $path = '/'.$path; $baseDir = $appBaseDir . ' . '; } } elseif (strpos($path, $vendorPath) === 0) { $path = substr($path, strlen($vendorPath)); $baseDir = '$vendorDir . '; } $exportedPaths[] = $baseDir.var_export($path, true); } $exportedPrefix = var_export($namespace, true); $namespacesFile .= " $exportedPrefix => "; if (count($exportedPaths) > 1) { $namespacesFile .= "array(".implode(', ',$exportedPaths)."),\n"; } else { $namespacesFile .= $exportedPaths[0].",\n"; } } } $namespacesFile .= ");\n"; file_put_contents($targetDir.'/autoload.php', $autoloadFile); file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile); copy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php'); } /** * Compiles an ordered list of namespace => path mappings * * @param array $packageMap array of array(package, installDir-relative-to-composer.json) * @return array array('psr-0' => array('Ns\\Foo' => array('installDir'))) */ public function parseAutoloads(array $packageMap) { $autoloads = array(); foreach ($packageMap as $item) { list($package, $installPath) = $item; if (null !== $package->getTargetDir()) { $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir())); } foreach ($package->getAutoload() as $type => $mapping) { foreach ($mapping as $namespace => $path) { $autoloads[$type][$namespace][] = empty($installPath) ? $path : $installPath.'/'.$path; } } } foreach ($autoloads as $type => $maps) { krsort($autoloads[$type]); } return $autoloads; } /** * Registers an autoloader based on an autoload map returned by parseAutoloads * * @param array $autoloads see parseAutoloads return value * @return ClassLoader */ public function createLoader(array $autoloads) { $loader = new ClassLoader(); if (isset($autoloads['psr-0'])) { foreach ($autoloads['psr-0'] as $namespace => $path) { $loader->add($namespace, $path); } } return $loader; } }