From 2f43e9aefb6912610d6279c4c7f623c8f043164e Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Tue, 13 Aug 2013 19:13:17 +0200 Subject: [PATCH] Load installed plugins at appropriate time and adapt tests accordingly --- src/Composer/Composer.php | 2 +- src/Composer/Factory.php | 11 ++- src/Composer/Installer/PluginInstaller.php | 53 +++-------- src/Composer/Plugin/PluginManager.php | 75 ++++++++++++++- .../Plugin/Fixtures/plugin-v1/composer.json | 2 +- .../Plugin/Fixtures/plugin-v2/composer.json | 2 +- .../Plugin/Fixtures/plugin-v3/composer.json | 2 +- .../Plugin/Fixtures/plugin-v4/composer.json | 2 +- .../Test/Plugin/PluginInstallerTest.php | 92 ++++++------------- 9 files changed, 122 insertions(+), 119 deletions(-) diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 32d48b771..02da7a3f5 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -55,7 +55,7 @@ class Composer private $installationManager; /** - * + * @var Plugin\PluginManager */ private $pluginManager; diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 1dd612b13..029833bf1 100644 --- a/src/Composer/Factory.php +++ b/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); } /** diff --git a/src/Composer/Installer/PluginInstaller.php b/src/Composer/Installer/PluginInstaller.php index dfcc97669..046aced45 100644 --- a/src/Composer/Installer/PluginInstaller.php +++ b/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); } } diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index aa08de2ef..24e4890ac 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/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(); + } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json index 969218ebc..996e5ee3e 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v1/composer.json +++ b/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": "" } }, diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json index 8ec717c46..c099da413 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v2/composer.json +++ b/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": "" } }, diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json index fe7aba7a4..3ba04e6f6 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v3/composer.json +++ b/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": "" } }, diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json index e2c2a4e47..10387a021 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v4/composer.json +++ b/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": "" } }, diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 28a9a768a..ab5696af8 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/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]); + + $plugins = $this->pm->getPlugins(); + $this->assertEquals('installer-v3', $plugins[1]->version); } } -class PluginInstallerMock extends PluginInstaller -{ - public function getInstallPath(PackageInterface $package) - { - $version = $package->getVersion(); - - return __DIR__.'/Fixtures/plugin-v'.$version[0].'/'; - } -}