Browse Source

Load installed plugins at appropriate time and adapt tests accordingly

Nils Adermann 11 years ago
parent
commit
2f43e9aefb

+ 1 - 1
src/Composer/Composer.php

@@ -55,7 +55,7 @@ class Composer
     private $installationManager;
 
     /**
-     *
+     * @var Plugin\PluginManager
      */
     private $pluginManager;
 

+ 6 - 5
src/Composer/Factory.php

@@ -249,6 +249,9 @@ class Factory
         $generator = new AutoloadGenerator($dispatcher);
         $composer->setAutoloadGenerator($generator);
 
+        $pm = $this->createPluginManager($composer, $io);
+        $composer->setPluginManager($pm);
+
         // add installers to the manager
         $this->createDefaultInstallers($im, $composer, $io);
 
@@ -264,9 +267,7 @@ class Factory
             $composer->setLocker($locker);
         }
 
-        $pm = $this->createPluginManager($composer);
-
-        $composer->setPluginManager($pm);
+        $pm->loadInstalledPlugins();
 
         return $composer;
     }
@@ -360,9 +361,9 @@ class Factory
     /**
      * @return Plugin\PluginManager
      */
-    protected function createPluginManager(Composer $composer)
+    protected function createPluginManager(Composer $composer, IOInterface $io)
     {
-        return new Plugin\PluginManager($composer);
+        return new Plugin\PluginManager($composer, $io);
     }
 
     /**

+ 11 - 42
src/Composer/Installer/PluginInstaller.php

@@ -37,15 +37,17 @@ class PluginInstaller extends LibraryInstaller
      */
     public function __construct(IOInterface $io, Composer $composer, $type = 'library')
     {
-        parent::__construct($io, $composer, $type);
+        parent::__construct($io, $composer, 'composer-plugin');
         $this->installationManager = $composer->getInstallationManager();
 
-        $repo = $composer->getRepositoryManager()->getLocalRepository();
-        foreach ($repo->getPackages() as $package) {
-            if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) {
-                $this->registerPlugin($package);
-            }
-        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function supports($packageType)
+    {
+        return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
     }
 
     /**
@@ -59,7 +61,7 @@ class PluginInstaller extends LibraryInstaller
         }
 
         parent::install($repo, $package);
-        $this->registerPlugin($package);
+        $this->composer->getPluginManager()->registerPackage($package);
     }
 
     /**
@@ -73,39 +75,6 @@ class PluginInstaller extends LibraryInstaller
         }
 
         parent::update($repo, $initial, $target);
-        $this->registerPlugin($target);
-    }
-
-    private function registerPlugin(PackageInterface $package)
-    {
-        $oldInstallerPlugin = ($package->getType() === 'composer-installer');
-
-        $downloadPath = $this->getInstallPath($package);
-
-        $extra = $package->getExtra();
-        $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
-
-        $generator = $this->composer->getAutoloadGenerator();
-        $map = $generator->parseAutoloads(array(array($package, $downloadPath)), new Package('dummy', '1.0.0.0', '1.0.0'));
-        $classLoader = $generator->createLoader($map);
-        $classLoader->register();
-
-        foreach ($classes as $class) {
-            if (class_exists($class, false)) {
-                $code = file_get_contents($classLoader->findFile($class));
-                $code = preg_replace('{^(\s*)class\s+(\S+)}mi', '$1class $2_composer_tmp'.self::$classCounter, $code);
-                eval('?>'.$code);
-                $class .= '_composer_tmp'.self::$classCounter;
-                self::$classCounter++;
-            }
-
-            $plugin = new $class($this->io, $this->composer);
-
-            if ($oldInstallerPlugin) {
-                $this->installationManager->addInstaller($installer);
-            } else {
-                $this->composer->getPluginManager()->addPlugin($plugin);
-            }
-        }
+        $this->composer->getPluginManager()->registerPackage($target);
     }
 }

+ 74 - 1
src/Composer/Plugin/PluginManager.php

@@ -13,6 +13,8 @@
 namespace Composer\Plugin;
 
 use Composer\Composer;
+use Composer\Package\Package;
+use Composer\IO\IOInterface;
 use Composer\Package\PackageInterface;
 
 /**
@@ -23,17 +25,34 @@ use Composer\Package\PackageInterface;
 class PluginManager
 {
     protected $composer;
+    protected $io;
 
     protected $plugins = array();
 
+    private static $classCounter = 0;
+
     /**
      * Initializes plugin manager
      *
      * @param Composer $composer
      */
-    public function __construct(Composer $composer)
+    public function __construct(Composer $composer, IOInterface $io)
     {
         $this->composer = $composer;
+        $this->io = $io;
+    }
+
+    public function loadInstalledPlugins()
+    {
+        $repo = $this->composer->getRepositoryManager()->getLocalRepository();
+
+        if ($repo) {
+            foreach ($repo->getPackages() as $package) {
+                if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) {
+                    $this->registerPackage($package);
+                }
+            }
+        }
     }
 
     /**
@@ -46,4 +65,58 @@ class PluginManager
         $this->plugins[] =  $plugin;
         $plugin->activate($this->composer);
     }
+
+    public function getPlugins()
+    {
+        return $this->plugins;
+    }
+
+    public function registerPackage(PackageInterface $package)
+    {
+        $oldInstallerPlugin = ($package->getType() === 'composer-installer');
+
+        $downloadPath = $this->getInstallPath($package);
+
+        $extra = $package->getExtra();
+        if (empty($extra['class'])) {
+            throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
+        }
+        $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
+
+        $generator = $this->composer->getAutoloadGenerator();
+        $map = $generator->parseAutoloads(array(array($package, $downloadPath)), new Package('dummy', '1.0.0.0', '1.0.0'));
+        $classLoader = $generator->createLoader($map);
+        $classLoader->register();
+
+        foreach ($classes as $class) {
+            if (class_exists($class, false)) {
+                $code = file_get_contents($classLoader->findFile($class));
+                $code = preg_replace('{^(\s*)class\s+(\S+)}mi', '$1class $2_composer_tmp'.self::$classCounter, $code);
+                eval('?>'.$code);
+                $class .= '_composer_tmp'.self::$classCounter;
+                self::$classCounter++;
+            }
+
+            $plugin = new $class($this->io, $this->composer);
+
+            if ($oldInstallerPlugin) {
+                $this->composer->getInstallationManager()->addInstaller($installer);
+            } else {
+                $this->addPlugin($plugin);
+            }
+        }
+    }
+
+    public function getInstallPath(PackageInterface $package)
+    {
+        $targetDir = $package->getTargetDir();
+
+        return $this->getPackageBasePath($package) . ($targetDir ? '/'.$targetDir : '');
+    }
+
+    protected function getPackageBasePath(PackageInterface $package)
+    {
+        $vendorDir = rtrim($this->composer->getConfig()->get('vendor-dir'), '/');
+        return ($vendorDir ? $vendorDir.'/' : '') . $package->getPrettyName();
+    }
 }

+ 1 - 1
tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json

@@ -1,5 +1,5 @@
 {
-    "name": "",
+    "name": "plugin-v1",
     "version": "1.0.0",
     "type": "composer-plugin",
     "autoload": { "psr-0": { "Installer": "" } },

+ 1 - 1
tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json

@@ -1,5 +1,5 @@
 {
-    "name": "",
+    "name": "plugin-v2",
     "version": "2.0.0",
     "type": "composer-plugin",
     "autoload": { "psr-0": { "Installer": "" } },

+ 1 - 1
tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json

@@ -1,5 +1,5 @@
 {
-    "name": "",
+    "name": "plugin-v3",
     "version": "3.0.0",
     "type": "composer-plugin",
     "autoload": { "psr-0": { "Installer": "" } },

+ 1 - 1
tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json

@@ -1,5 +1,5 @@
 {
-    "name": "",
+    "name": "plugin-v4",
     "version": "4.0.0",
     "type": "composer-plugin",
     "autoload": { "psr-0": { "Installer": "" } },

+ 26 - 66
tests/Composer/Test/Plugin/PluginInstallerTest.php

@@ -42,14 +42,6 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
-        $this->im = $this->getMockBuilder('Composer\Installer\InstallationManager')
-            ->disableOriginalConstructor()
-            ->getMock();
-
-        $this->pm = $this->getMockBuilder('Composer\Plugin\PluginManager')
-            ->disableOriginalConstructor()
-            ->getMock();
-
         $this->repository = $this->getMock('Composer\Repository\InstalledRepositoryInterface');
 
         $rm = $this->getMockBuilder('Composer\Repository\RepositoryManager')
@@ -68,11 +60,12 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
         $config = new Config();
         $this->composer->setConfig($config);
         $this->composer->setDownloadManager($dm);
-        $this->composer->setInstallationManager($this->im);
-        $this->composer->setPluginManager($this->pm);
         $this->composer->setRepositoryManager($rm);
         $this->composer->setAutoloadGenerator($this->autoloadGenerator);
 
+        $this->pm = new \Composer\Plugin\PluginManager($this->composer, $this->io);
+        $this->composer->setPluginManager($this->pm);
+
         $config->merge(array(
             'config' => array(
                 'vendor-dir' => __DIR__.'/Fixtures/',
@@ -87,17 +80,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
             ->expects($this->once())
             ->method('getPackages')
             ->will($this->returnValue(array()));
-        $installer = new PluginInstallerMock($this->io, $this->composer);
-
-        $test = $this;
-        $this->pm
-            ->expects($this->once())
-            ->method('addPlugin')
-            ->will($this->returnCallback(function ($installer) use ($test) {
-                $test->assertEquals('installer-v1', $installer->version);
-            }));
+        $installer = new PluginInstaller($this->io, $this->composer);
+        $this->pm->loadInstalledPlugins();
 
         $installer->install($this->repository, $this->packages[0]);
+
+        $plugins = $this->pm->getPlugins();
+        $this->assertEquals('installer-v1', $plugins[0]->version);
     }
 
     public function testInstallMultiplePlugins()
@@ -106,28 +95,16 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
             ->expects($this->once())
             ->method('getPackages')
             ->will($this->returnValue(array()));
-
-        $installer = new PluginInstallerMock($this->io, $this->composer);
-
-        $test = $this;
-
-        $this->pm
-            ->expects($this->at(0))
-            ->method('addPlugin')
-            ->will($this->returnCallback(function ($plugin) use ($test) {
-                $test->assertEquals('plugin1', $plugin->name);
-                $test->assertEquals('installer-v4', $plugin->version);
-            }));
-
-        $this->pm
-            ->expects($this->at(1))
-            ->method('addPlugin')
-            ->will($this->returnCallback(function ($plugin) use ($test) {
-                $test->assertEquals('plugin2', $plugin->name);
-                $test->assertEquals('installer-v4', $plugin->version);
-            }));
+        $installer = new PluginInstaller($this->io, $this->composer);
+        $this->pm->loadInstalledPlugins();
 
         $installer->install($this->repository, $this->packages[3]);
+
+        $plugins = $this->pm->getPlugins();
+        $this->assertEquals('plugin1', $plugins[0]->name);
+        $this->assertEquals('installer-v4', $plugins[0]->version);
+        $this->assertEquals('plugin2', $plugins[1]->name);
+        $this->assertEquals('installer-v4', $plugins[1]->version);
     }
 
     public function testUpgradeWithNewClassName()
@@ -140,17 +117,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
             ->expects($this->exactly(2))
             ->method('hasPackage')
             ->will($this->onConsecutiveCalls(true, false));
-        $installer = new PluginInstallerMock($this->io, $this->composer);
-
-        $test = $this;
-        $this->pm
-            ->expects($this->once())
-            ->method('addPlugin')
-            ->will($this->returnCallback(function ($plugin) use ($test) {
-                $test->assertEquals('installer-v2', $plugin->version);
-            }));
+        $installer = new PluginInstaller($this->io, $this->composer);
+        $this->pm->loadInstalledPlugins();
 
         $installer->update($this->repository, $this->packages[0], $this->packages[1]);
+
+        $plugins = $this->pm->getPlugins();
+        $this->assertEquals('installer-v2', $plugins[1]->version);
     }
 
     public function testUpgradeWithSameClassName()
@@ -163,26 +136,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
             ->expects($this->exactly(2))
             ->method('hasPackage')
             ->will($this->onConsecutiveCalls(true, false));
-        $installer = new PluginInstallerMock($this->io, $this->composer);
-
-        $test = $this;
-        $this->pm
-            ->expects($this->once())
-            ->method('addPlugin')
-            ->will($this->returnCallback(function ($plugin) use ($test) {
-                $test->assertEquals('installer-v3', $plugin->version);
-            }));
+        $installer = new PluginInstaller($this->io, $this->composer);
+        $this->pm->loadInstalledPlugins();
 
         $installer->update($this->repository, $this->packages[1], $this->packages[2]);
-    }
-}
 
-class PluginInstallerMock extends PluginInstaller
-{
-    public function getInstallPath(PackageInterface $package)
-    {
-        $version = $package->getVersion();
-
-        return __DIR__.'/Fixtures/plugin-v'.$version[0].'/';
+        $plugins = $this->pm->getPlugins();
+        $this->assertEquals('installer-v3', $plugins[1]->version);
     }
 }
+