diff --git a/doc/04-schema.md b/doc/04-schema.md index 0bb286f3e..3c179eb63 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -225,6 +225,16 @@ Example: } } +### include-paths + +A list of paths which should get appended to PHP's `include_path`. + +Example: + + { + "include-paths": ["lib/"] + } + ### target-dir Defines the installation target. diff --git a/res/composer-schema.json b/res/composer-schema.json index f95b4e91e..9db68ab07 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -146,6 +146,13 @@ "type": "string" } }, + "include-paths": { + "type": ["array"], + "description": "A list of directories which should get added to PHP's include path.", + "items": { + "type": "string" + } + }, "scripts": { "type": ["object"], "description": "Scripts listeners that will be executed before/after some events.", diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index dcab0ed6c..d92080ea5 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -35,6 +35,13 @@ if (!class_exists('Composer\\Autoload\\ClassLoader', false)) { require __DIR__.'/ClassLoader.php'; } +$includePaths = require __DIR__.'/include_paths.php'; + +if ($includePaths) { + array_unshift($includePaths, get_include_path()); + set_include_path(join(PATH_SEPARATOR, $includePaths)); +} + return call_user_func(function() { $loader = new \Composer\Autoload\ClassLoader(); @@ -134,6 +141,7 @@ EOF; file_put_contents($targetDir.'/autoload.php', $autoloadFile); file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile); file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile); + file_put_contents($targetDir.'/include_paths.php', $this->getIncludePathsFile($packageMap)); copy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php'); } @@ -205,4 +213,25 @@ EOF; return $loader; } + + protected function getIncludePathsFile(array $packageMap) + { + $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) { + $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath; + } + } + + return sprintf( + "aliasOf->getAutoload(); } + public function getIncludePaths() + { + return $this->aliasOf->getIncludePaths(); + } public function getRepositories() { return $this->aliasOf->getRepositories(); diff --git a/src/Composer/Package/Loader/ArrayLoader.php b/src/Composer/Package/Loader/ArrayLoader.php index 88dbc94a4..a72a50f81 100644 --- a/src/Composer/Package/Loader/ArrayLoader.php +++ b/src/Composer/Package/Loader/ArrayLoader.php @@ -169,6 +169,10 @@ class ArrayLoader $package->setAutoload($config['autoload']); } + if (isset($config['include-paths'])) { + $package->setIncludePaths($config['include-paths']); + } + return $package; } diff --git a/src/Composer/Package/MemoryPackage.php b/src/Composer/Package/MemoryPackage.php index 2c3502502..8944f9b47 100644 --- a/src/Composer/Package/MemoryPackage.php +++ b/src/Composer/Package/MemoryPackage.php @@ -56,6 +56,7 @@ class MemoryPackage extends BasePackage protected $recommends = array(); protected $suggests = array(); protected $autoload = array(); + protected $includePaths = array(); /** * Creates a new in memory package. @@ -623,4 +624,22 @@ class MemoryPackage extends BasePackage { return $this->autoload; } + + /** + * Sets the list of paths added to PHP's include path. + * + * @param array $includePaths List of directories. + */ + public function setIncludePaths(array $includePaths) + { + $this->includePaths = $includePaths; + } + + /** + * {@inheritDoc} + */ + public function getIncludePaths() + { + return $this->includePaths; + } } diff --git a/src/Composer/Package/PackageInterface.php b/src/Composer/Package/PackageInterface.php index 97997f093..ee2fcedc0 100644 --- a/src/Composer/Package/PackageInterface.php +++ b/src/Composer/Package/PackageInterface.php @@ -249,6 +249,14 @@ interface PackageInterface */ function getAutoload(); + /** + * Returns a list of directories which should get added to PHP's + * include path. + * + * @return array + */ + function getIncludePaths(); + /** * Returns an array of repositories * diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index 79435b7bd..0d9bdc1a7 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -253,6 +253,89 @@ class AutoloadGeneratorTest extends TestCase $this->assertAutoloadFiles('override_vendors', $this->vendorDir.'/.composer'); } + public function testIncludePathFileGeneration() + { + $package = new MemoryPackage('a', '1.0', '1.0'); + $packages = array(); + + $a = new MemoryPackage("a/a", "1.0", "1.0"); + $a->setIncludePaths(array("lib/")); + + $b = new MemoryPackage("b/b", "1.0", "1.0"); + $b->setIncludePaths(array("library")); + + $packages[] = $a; + $packages[] = $b; + + $this->repository->expects($this->once()) + ->method("getPackages") + ->will($this->returnValue($packages)); + + mkdir($this->vendorDir."/.composer", 0777, true); + + $this->generator->dump($this->repository, $package, $this->im, $this->vendorDir."/.composer"); + + $this->assertEquals( + array( + $this->vendorDir."/a/a/lib/", + $this->vendorDir."/b/b/library" + ), + require($this->vendorDir."/.composer/include_paths.php") + ); + } + + public function testIncludePathsAreAppendedInAutoloadFile() + { + $package = new MemoryPackage('a', '1.0', '1.0'); + $packages = array(); + + $a = new MemoryPackage("a/a", "1.0", "1.0"); + $a->setIncludePaths(array("lib/")); + + $packages[] = $a; + + $this->repository->expects($this->once()) + ->method("getPackages") + ->will($this->returnValue($packages)); + + mkdir($this->vendorDir."/.composer", 0777, true); + + $this->generator->dump($this->repository, $package, $this->im, $this->vendorDir."/.composer"); + + $oldIncludePath = get_include_path(); + + require($this->vendorDir."/.composer/autoload.php"); + + $this->assertEquals( + $oldIncludePath.PATH_SEPARATOR.$this->vendorDir."/a/a/lib/", + get_include_path() + ); + + set_include_path($oldIncludePath); + } + + public function testIncludePathFileGenerationWithoutPaths() + { + $package = new MemoryPackage('a', '1.0', '1.0'); + $packages = array(); + + $a = new MemoryPackage("a/a", "1.0", "1.0"); + $packages[] = $a; + + $this->repository->expects($this->once()) + ->method("getPackages") + ->will($this->returnValue($packages)); + + mkdir($this->vendorDir."/.composer", 0777, true); + + $this->generator->dump($this->repository, $package, $this->im, $this->vendorDir."/.composer"); + + $this->assertEquals( + array(), + require($this->vendorDir."/.composer/include_paths.php") + ); + } + private function createClassFile($basedir) { if (!is_dir($basedir.'/.composersrc')) {