From 5c5e962b5a0329ea19652c8537e16a981cfa601c Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Sat, 2 Jun 2012 18:18:33 +0200 Subject: [PATCH] Add Files Autoloading key. This is a necessary feature to allow purely or partly functional libraries to be "autoloadable" by composer by calling require_once on every file in the "autoload"."files" list. --- doc/04-schema.md | 14 ++++++++- res/composer-schema.json | 4 +++ src/Composer/Autoload/AutoloadGenerator.php | 15 +++++++-- .../Test/Autoload/AutoloadGeneratorTest.php | 31 +++++++++++++++++++ .../Autoload/Fixtures/autoload_target_dir.php | 2 ++ 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/doc/04-schema.md b/doc/04-schema.md index 0dfe86b90..14dd77093 100644 --- a/doc/04-schema.md +++ b/doc/04-schema.md @@ -344,7 +344,7 @@ Example: Autoload mapping for a PHP autoloader. Currently [PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) -autoloading and classmap generation are supported. PSR-0 is the recommended way though +autoloading, classmap generation and files are supported. PSR-0 is the recommended way though since it offers greater flexibility (no need to regenerate the autoloader when you add classes). @@ -393,6 +393,18 @@ Example: } } +If you want to require certain files explicitly on every request then you can use +the 'files' autoloading mechanism. This is useful if your package includes PHP functions +that cannot be autoloaded by PHP. + +Example: + + { + "autoload": { + "files": ["src/MyLibrary/functions.php"] + } + } + ### include-path > **DEPRECATED**: This is only present to support legacy projects, and all new code diff --git a/res/composer-schema.json b/res/composer-schema.json index 8e54bd934..285b01cee 100644 --- a/res/composer-schema.json +++ b/res/composer-schema.json @@ -135,6 +135,10 @@ "classmap": { "type": "array", "description": "This is an array of directories that contain classes to be included in the class-map generation process." + }, + "files": { + "type": "array", + "description": "This is an array of files that are always required on every request." } } }, diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 4ae8bd9a7..d10e3bd1f 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -121,12 +121,19 @@ EOF; } $classmapFile .= ");\n"; + $filesCode = ""; + $autoloads['files'] = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($autoloads['files'])); + foreach ($autoloads['files'] as $functionFile) { + $filesCode .= 'require "' . $filesystem->findShortestPath(getcwd(), $functionFile) .'";' . "\n"; + } + $filesCode = rtrim($filesCode); + file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile); file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile); if ($includePathFile = $this->getIncludePathsFile($packageMap, $filesystem, $relVendorPath, $vendorPath, $vendorPathCode, $appBaseDirCode)) { file_put_contents($targetDir.'/include_paths.php', $includePathFile); } - file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, true, true, (Boolean) $includePathFile, $targetDirLoader)); + file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, true, true, (Boolean) $includePathFile, $targetDirLoader, $filesCode)); copy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php'); // TODO BC feature, remove after June 15th @@ -173,7 +180,7 @@ EOF; */ public function parseAutoloads(array $packageMap) { - $autoloads = array('classmap' => array(), 'psr-0' => array()); + $autoloads = array('classmap' => array(), 'psr-0' => array(), 'files' => array()); foreach ($packageMap as $item) { list($package, $installPath) = $item; @@ -281,7 +288,7 @@ EOF; return $baseDir.var_export($path, true); } - protected function getAutoloadFile($vendorPathToTargetDirCode, $usePSR0, $useClassMap, $useIncludePath, $targetDirLoader) + protected function getAutoloadFile($vendorPathToTargetDirCode, $usePSR0, $useClassMap, $useIncludePath, $targetDirLoader, $filesCode) { $file = <<
assertAutoloadFiles('classmap5', $this->vendorDir.'/composer', 'classmap'); } + public function testFilesAutoloadGeneration() + { + $package = new MemoryPackage('a', '1.0', '1.0'); + + $packages = array(); + $packages[] = $a = new MemoryPackage('a/a', '1.0', '1.0'); + $packages[] = $b = new MemoryPackage('b/b', '1.0', '1.0'); + $a->setAutoload(array('files' => array('test.php'))); + $b->setAutoload(array('files' => array('test2.php'))); + + $this->repository->expects($this->once()) + ->method('getPackages') + ->will($this->returnValue($packages)); + + mkdir($this->vendorDir.'/a/a', 0777, true); + mkdir($this->vendorDir.'/b/b', 0777, true); + file_put_contents($this->vendorDir.'/a/a/test.php', 'vendorDir.'/b/b/test2.php', 'generator->dump($this->repository, $package, $this->im, $this->vendorDir.'/composer'); + + $code = file_get_contents($this->vendorDir.'/autoload.php'); + $this->assertContains('a/a/test.php', $code); + $this->assertContains('b/b/test2.php', $code); + + include $this->vendorDir . '/autoload.php'; + + $this->assertTrue(function_exists('testFilesAutoloadGeneration1')); + $this->assertTrue(function_exists('testFilesAutoloadGeneration2')); + } + public function testOverrideVendorsAutoloading() { $package = new MemoryPackage('a', '1.0', '1.0'); diff --git a/tests/Composer/Test/Autoload/Fixtures/autoload_target_dir.php b/tests/Composer/Test/Autoload/Fixtures/autoload_target_dir.php index a4012aab9..ce92241ec 100644 --- a/tests/Composer/Test/Autoload/Fixtures/autoload_target_dir.php +++ b/tests/Composer/Test/Autoload/Fixtures/autoload_target_dir.php @@ -5,6 +5,8 @@ if (!class_exists('Composer\\Autoload\\ClassLoader', false)) { require __DIR__ . '/composer' . '/ClassLoader.php'; } + + return call_user_func(function() { $loader = new \Composer\Autoload\ClassLoader(); $composerDir = __DIR__ . '/composer';