Browse Source

Support multiple installers in a composer-installer package.

Andrew Short 12 years ago
parent
commit
e0a1d9ef58

+ 2 - 1
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:
 

+ 12 - 11
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);
+        }
     }
 }

+ 20 - 0
tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Custom1.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace Installer;
+
+use Composer\Installer\InstallerInterface;
+use Composer\Package\PackageInterface;
+use Composer\Repository\InstalledRepositoryInterface;
+
+class Custom1 implements InstallerInterface
+{
+    public $name = 'custom1';
+    public $version = 'installer-v4';
+
+    public function supports($packageType) {}
+    public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package) {}
+    public function install(InstalledRepositoryInterface $repo, PackageInterface $package) {}
+    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) {}
+    public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) {}
+    public function getInstallPath(PackageInterface $package) {}
+}

+ 20 - 0
tests/Composer/Test/Installer/Fixtures/installer-v4/Installer/Custom2.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace Installer;
+
+use Composer\Installer\InstallerInterface;
+use Composer\Package\PackageInterface;
+use Composer\Repository\InstalledRepositoryInterface;
+
+class Custom2 implements InstallerInterface
+{
+    public $name = 'custom2';
+    public $version = 'installer-v4';
+
+    public function supports($packageType) {}
+    public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package) {}
+    public function install(InstalledRepositoryInterface $repo, PackageInterface $package) {}
+    public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) {}
+    public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) {}
+    public function getInstallPath(PackageInterface $package) {}
+}

+ 12 - 0
tests/Composer/Test/Installer/Fixtures/installer-v4/composer.json

@@ -0,0 +1,12 @@
+{
+    "name": "",
+    "version": "4.0.0",
+    "type": "composer-installer",
+    "autoload": { "psr-0": { "Installer": "" } },
+    "extra": {
+        "class": [
+            "Installer\\Custom1",
+            "Installer\\Custom2"
+        ]
+    }
+}

+ 38 - 1
tests/Composer/Test/Installer/InstallerInstallerTest.php

@@ -22,7 +22,7 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase
     {
         $loader = new JsonLoader();
         $this->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