2011-10-16 18:04:29 +00:00
< ? php
/*
* This file is part of Composer .
*
* ( c ) Nils Adermann < naderman @ naderman . de >
* Jordi Boggiano < j . boggiano @ seld . be >
*
* 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 ;
2012-02-09 17:45:28 +00:00
use Composer\Util\Filesystem ;
2011-10-16 18:04:29 +00:00
/**
* @ author Igor Wiedler < igor @ wiedler . ch >
2011-10-23 19:23:37 +00:00
* @ author Jordi Boggiano < j . boggiano @ seld . be >
2011-10-16 18:04:29 +00:00
*/
class AutoloadGenerator
{
2012-04-19 19:55:35 +00:00
public function dump ( RepositoryInterface $localRepo , PackageInterface $mainPackage , InstallationManager $installationManager , $targetDir , $bcLinks = false )
2011-10-16 18:04:29 +00:00
{
2011-12-03 22:20:36 +00:00
$filesystem = new Filesystem ();
2012-04-15 15:48:30 +00:00
$filesystem -> ensureDirectoryExists ( $installationManager -> getVendorPath ());
$filesystem -> ensureDirectoryExists ( $targetDir );
2011-12-03 22:20:36 +00:00
$vendorPath = strtr ( realpath ( $installationManager -> getVendorPath ()), '\\' , '/' );
2012-03-22 09:11:48 +00:00
$relVendorPath = $filesystem -> findShortestPath ( getcwd (), $vendorPath , true );
2011-12-04 21:13:11 +00:00
$vendorDirCode = $filesystem -> findShortestPathCode ( realpath ( $targetDir ), $vendorPath , true );
2011-12-03 22:20:36 +00:00
2012-04-19 08:51:57 +00:00
$appBaseDirCode = $filesystem -> findShortestPathCode ( $vendorPath , getcwd (), true );
$appBaseDirCode = str_replace ( '__DIR__' , '$vendorDir' , $appBaseDirCode );
2012-03-10 00:59:59 +00:00
2011-12-03 22:20:36 +00:00
$namespacesFile = <<< EOF
2011-10-30 19:29:06 +00:00
< ? php
2011-10-29 05:24:30 +00:00
2011-10-30 19:29:06 +00:00
// autoload_namespace.php generated by Composer
2011-10-16 18:04:29 +00:00
2011-12-03 22:20:36 +00:00
\ $vendorDir = $vendorDirCode ;
2012-04-19 08:51:57 +00:00
\ $baseDir = $appBaseDirCode ;
2011-11-20 21:02:22 +00:00
2011-10-30 19:29:06 +00:00
return array (
2011-10-16 18:04:29 +00:00
EOF ;
2012-02-07 10:12:03 +00:00
$packageMap = $this -> buildPackageMap ( $installationManager , $mainPackage , $localRepo -> getPackages ());
2011-11-03 21:22:12 +00:00
$autoloads = $this -> parseAutoloads ( $packageMap );
2011-10-30 19:29:06 +00:00
2012-03-10 00:59:59 +00:00
foreach ( $autoloads [ 'psr-0' ] as $namespace => $paths ) {
$exportedPaths = array ();
foreach ( $paths as $path ) {
2012-04-19 08:51:57 +00:00
$exportedPaths [] = $this -> getPathCode ( $filesystem , $relVendorPath , $vendorPath , $path );
2012-03-10 00:59:59 +00:00
}
$exportedPrefix = var_export ( $namespace , true );
$namespacesFile .= " $exportedPrefix => " ;
if ( count ( $exportedPaths ) > 1 ) {
$namespacesFile .= " array( " . implode ( ', ' , $exportedPaths ) . " ), \n " ;
} else {
$namespacesFile .= $exportedPaths [ 0 ] . " , \n " ;
2011-10-16 18:04:29 +00:00
}
}
2011-10-30 19:29:06 +00:00
$namespacesFile .= " ); \n " ;
2011-10-16 18:04:29 +00:00
2012-03-10 00:59:59 +00:00
$classmapFile = <<< EOF
< ? php
// autoload_classmap.php generated by Composer
\ $vendorDir = $vendorDirCode ;
2012-04-19 08:51:57 +00:00
\ $baseDir = $appBaseDirCode ;
2012-03-10 00:59:59 +00:00
return array (
EOF ;
2012-03-05 12:26:46 +00:00
2012-03-10 00:59:59 +00:00
// flatten array
$autoloads [ 'classmap' ] = new \RecursiveIteratorIterator ( new \RecursiveArrayIterator ( $autoloads [ 'classmap' ]));
foreach ( $autoloads [ 'classmap' ] as $dir ) {
foreach ( ClassMapGenerator :: createMap ( $dir ) as $class => $path ) {
2012-03-22 09:11:48 +00:00
$path = '/' . $filesystem -> findShortestPath ( getcwd (), $path , true );
2012-03-10 00:59:59 +00:00
$classmapFile .= ' ' . var_export ( $class , true ) . ' => $baseDir . ' . var_export ( $path , true ) . " , \n " ;
}
}
$classmapFile .= " ); \n " ;
2012-03-05 13:10:01 +00:00
2011-10-30 19:29:06 +00:00
file_put_contents ( $targetDir . '/autoload_namespaces.php' , $namespacesFile );
2012-03-10 00:59:59 +00:00
file_put_contents ( $targetDir . '/autoload_classmap.php' , $classmapFile );
2012-04-19 08:51:57 +00:00
if ( $includePathFile = $this -> getIncludePathsFile ( $packageMap , $filesystem , $relVendorPath , $vendorPath , $vendorDirCode , $appBaseDirCode )) {
2012-04-08 15:42:57 +00:00
file_put_contents ( $targetDir . '/include_paths.php' , $includePathFile );
}
file_put_contents ( $targetDir . '/autoload.php' , $this -> getAutoloadFile ( true , true , ( Boolean ) $includePathFile ));
2012-01-22 21:39:54 +00:00
copy ( __DIR__ . '/ClassLoader.php' , $targetDir . '/ClassLoader.php' );
2012-04-19 19:55:35 +00:00
// TODO BC feature, add E_DEPRECATED in autoload.php on April 30th, remove after May 30th
if ( $bcLinks ) {
file_put_contents ( $targetDir . '/.composer/autoload_namespaces.php' , " <?php \n // Deprecated file, use the one in root of vendor dir \n return include dirname(__DIR__).'/autoload_namespaces.php'; \n " );
file_put_contents ( $targetDir . '/.composer/autoload_classmap.php' , " <?php \n // Deprecated file, use the one in root of vendor dir \n return include dirname(__DIR__).'/autoload_classmap.php'; \n " );
file_put_contents ( $targetDir . '/.composer/autoload.php' , " <?php \n // Deprecated file, use the one in root of vendor dir \n return include dirname(__DIR__).'/autoload.php'; \n " );
file_put_contents ( $targetDir . '/.composer/ClassLoader.php' , " <?php \n // Deprecated file, use the one in root of vendor dir \n return include dirname(__DIR__).'/ClassLoader.php'; \n " );
if ( $includePathFile ) {
file_put_contents ( $targetDir . '/.composer/include_paths.php' , " <?php \n // Deprecated file, use the one in root of vendor dir \n return include dirname(__DIR__).'/include_paths.php'; \n " );
}
}
2011-10-16 18:04:29 +00:00
}
2012-02-07 10:12:03 +00:00
public function buildPackageMap ( InstallationManager $installationManager , PackageInterface $mainPackage , array $packages )
{
// build package => install path map
$packageMap = array ();
// add main package
$packageMap [] = array ( $mainPackage , '' );
foreach ( $packages as $package ) {
$packageMap [] = array (
$package ,
$installationManager -> getInstallPath ( $package )
);
}
return $packageMap ;
}
2011-11-03 21:22:12 +00:00
/**
* Compiles an ordered list of namespace => path mappings
*
* @ param array $packageMap array of array ( package , installDir - relative - to - composer . json )
2012-01-13 03:14:30 +00:00
* @ return array array ( 'psr-0' => array ( 'Ns\\Foo' => array ( 'installDir' )))
2011-11-03 21:22:12 +00:00
*/
public function parseAutoloads ( array $packageMap )
2011-10-16 18:04:29 +00:00
{
2012-03-10 00:59:59 +00:00
$autoloads = array ( 'classmap' => array (), 'psr-0' => array ());
2011-11-03 21:22:12 +00:00
foreach ( $packageMap as $item ) {
2011-10-16 18:04:29 +00:00
list ( $package , $installPath ) = $item ;
if ( null !== $package -> getTargetDir ()) {
$installPath = substr ( $installPath , 0 , - strlen ( '/' . $package -> getTargetDir ()));
}
foreach ( $package -> getAutoload () as $type => $mapping ) {
2012-04-17 12:01:24 +00:00
// skip misconfigured packages
if ( ! is_array ( $mapping )) {
continue ;
}
2012-03-28 15:09:07 +00:00
foreach ( $mapping as $namespace => $paths ) {
foreach (( array ) $paths as $path ) {
$autoloads [ $type ][ $namespace ][] = empty ( $installPath ) ? $path : $installPath . '/' . $path ;
}
2011-11-03 20:05:01 +00:00
}
2011-10-16 18:04:29 +00:00
}
}
2011-11-03 20:05:01 +00:00
foreach ( $autoloads as $type => $maps ) {
2012-01-13 03:14:30 +00:00
krsort ( $autoloads [ $type ]);
2011-11-03 20:05:01 +00:00
}
2011-10-16 18:04:29 +00:00
return $autoloads ;
}
2011-11-03 21:22:12 +00:00
/**
* 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' ])) {
2012-01-13 03:14:30 +00:00
foreach ( $autoloads [ 'psr-0' ] as $namespace => $path ) {
$loader -> add ( $namespace , $path );
2011-11-03 21:22:12 +00:00
}
}
return $loader ;
}
2012-04-04 07:46:31 +00:00
2012-04-19 08:51:57 +00:00
protected function getIncludePathsFile ( array $packageMap , Filesystem $filesystem , $relVendorPath , $vendorPath , $vendorDirCode , $appBaseDirCode )
2012-04-04 07:46:31 +00:00
{
$includePaths = array ();
foreach ( $packageMap as $item ) {
list ( $package , $installPath ) = $item ;
if ( null !== $package -> getTargetDir ()) {
$installPath = substr ( $installPath , 0 , - strlen ( '/' . $package -> getTargetDir ()));
}
foreach ( $package -> getIncludePaths () as $includePath ) {
2012-04-19 08:51:57 +00:00
$includePath = trim ( $includePath , '/' );
2012-04-04 07:46:31 +00:00
$includePaths [] = empty ( $installPath ) ? $includePath : $installPath . '/' . $includePath ;
}
}
2012-04-08 15:42:57 +00:00
if ( ! $includePaths ) {
return ;
}
2012-04-19 08:51:57 +00:00
$includePathsFile = <<< EOF
< ? php
// include_paths.php generated by Composer
\ $vendorDir = $vendorDirCode ;
\ $baseDir = $appBaseDirCode ;
return array (
EOF ;
foreach ( $includePaths as $path ) {
$includePathsFile .= " " . $this -> getPathCode ( $filesystem , $relVendorPath , $vendorPath , $path ) . " , \n " ;
}
return $includePathsFile . " ); \n " ;
}
protected function getPathCode ( Filesystem $filesystem , $relVendorPath , $vendorPath , $path )
{
$path = strtr ( $path , '\\' , '/' );
$baseDir = '' ;
if ( ! $filesystem -> isAbsolutePath ( $path )) {
if ( strpos ( $path , $relVendorPath ) === 0 ) {
// path starts with vendor dir
$path = substr ( $path , strlen ( $relVendorPath ));
$baseDir = '$vendorDir . ' ;
} else {
$path = '/' . $path ;
$baseDir = '$baseDir . ' ;
}
} elseif ( strpos ( $path , $vendorPath ) === 0 ) {
$path = substr ( $path , strlen ( $vendorPath ));
$baseDir = '$vendorDir . ' ;
}
return $baseDir . var_export ( $path , true );
2012-04-04 07:46:31 +00:00
}
2012-04-08 15:42:57 +00:00
protected function getAutoloadFile ( $usePSR0 , $useClassMap , $useIncludePath )
{
$file = <<< 'HEADER'
< ? php
// autoload.php generated by Composer
if ( ! class_exists ( 'Composer\\Autoload\\ClassLoader' , false )) {
require __DIR__ . '/ClassLoader.php' ;
}
return call_user_func ( function () {
$loader = new \Composer\Autoload\ClassLoader ();
HEADER ;
if ( $useIncludePath ) {
$file .= <<< 'INCLUDE_PATH'
$includePaths = require __DIR__ . '/include_paths.php' ;
array_unshift ( $includePaths , get_include_path ());
set_include_path ( join ( PATH_SEPARATOR , $includePaths ));
INCLUDE_PATH ;
}
if ( $usePSR0 ) {
$file .= <<< 'PSR0'
$map = require __DIR__ . '/autoload_namespaces.php' ;
foreach ( $map as $namespace => $path ) {
$loader -> add ( $namespace , $path );
}
PSR0 ;
}
if ( $useClassMap ) {
$file .= <<< 'CLASSMAP'
$classMap = require __DIR__ . '/autoload_classmap.php' ;
if ( $classMap ) {
$loader -> addClassMap ( $classMap );
}
CLASSMAP ;
}
return $file . <<< 'FOOTER'
$loader -> register ();
return $loader ;
});
FOOTER ;
}
2011-10-16 18:04:29 +00:00
}