diff --git a/doc/articles/custom-installers.md b/doc/articles/custom-installers.md index f69e90f0c..1f3d68f10 100644 --- a/doc/articles/custom-installers.md +++ b/doc/articles/custom-installers.md @@ -66,7 +66,8 @@ requirements: 1. the [type][1] attribute must be `composer-installer`. 2. the [extra][2] attribute must contain an element `class` defining the - class name of the installer (including namespace). + class name of the installer (including namespace). If a package contains + multiple installers this can be array of class names. Example: diff --git a/src/Composer/Installer/InstallerInstaller.php b/src/Composer/Installer/InstallerInstaller.php index 582817f93..70bf22b9c 100644 --- a/src/Composer/Installer/InstallerInstaller.php +++ b/src/Composer/Installer/InstallerInstaller.php @@ -83,23 +83,24 @@ class InstallerInstaller extends LibraryInstaller $downloadPath = $this->getInstallPath($package); $extra = $package->getExtra(); - $class = $extra['class']; + $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']); $generator = new AutoloadGenerator; $map = $generator->parseAutoloads(array(array($package, $downloadPath))); $classLoader = $generator->createLoader($map); $classLoader->register(); - if (class_exists($class, false)) { - $code = file_get_contents($classLoader->findFile($class)); - $code = preg_replace('{^class\s+(\S+)}mi', 'class $1_composer_tmp'.self::$classCounter, $code); - eval('?>'.$code); - $class .= '_composer_tmp'.self::$classCounter; - self::$classCounter++; - } + foreach ($classes as $class) { + if (class_exists($class, false)) { + $code = file_get_contents($classLoader->findFile($class)); + $code = preg_replace('{^class\s+(\S+)}mi', 'class $1_composer_tmp'.self::$classCounter, $code); + eval('?>'.$code); + $class .= '_composer_tmp'.self::$classCounter; + self::$classCounter++; + } - $extra = $package->getExtra(); - $installer = new $class($this->vendorDir, $this->binDir, $this->downloadManager, $this->io); - $this->installationManager->addInstaller($installer); + $installer = new $class($this->vendorDir, $this->binDir, $this->downloadManager, $this->io); + $this->installationManager->addInstaller($installer); + } } } diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Custom1.php b/tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Custom1.php new file mode 100644 index 000000000..a626caa3c --- /dev/null +++ b/tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Custom1.php @@ -0,0 +1,20 @@ +packages = array(); - for ($i = 1; $i <= 3; $i++) { + for ($i = 1; $i <= 4; $i++) { $this->packages[] = $loader->load(__DIR__.'/Fixtures/installer-v'.$i.'/composer.json'); } @@ -58,6 +58,43 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase $installer->install($this->repository, $this->packages[0]); } + public function testInstallMultipleInstallers() + { + $this->repository + ->expects($this->once()) + ->method('getPackages') + ->will($this->returnValue(array())); + + $installer = new InstallerInstallerMock( + __DIR__.'/Fixtures/', + __DIR__.'/Fixtures/bin', + $this->dm, + $this->io, + $this->im, + array($this->repository) + ); + + $test = $this; + + $this->im + ->expects($this->at(0)) + ->method('addInstaller') + ->will($this->returnCallback(function ($installer) use ($test) { + $test->assertEquals('custom1', $installer->name); + $test->assertEquals('installer-v4', $installer->version); + })); + + $this->im + ->expects($this->at(1)) + ->method('addInstaller') + ->will($this->returnCallback(function ($installer) use ($test) { + $test->assertEquals('custom2', $installer->name); + $test->assertEquals('installer-v4', $installer->version); + })); + + $installer->install($this->repository, $this->packages[3]); + } + public function testUpgradeWithNewClassName() { $this->repository