From ba909d8795c442307f81f244e31168b946f1159a Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 28 Apr 2016 21:12:26 +0100 Subject: [PATCH] Avoid duplicate commands, and pass plugin to ctor args for capabilities, refs #3377 --- src/Composer/Console/Application.php | 12 +++++++++--- src/Composer/Plugin/Capability/CommandProvider.php | 5 +++++ src/Composer/Plugin/PluginManager.php | 1 + .../Fixtures/plugin-v8/Installer/CommandProvider.php | 11 +++++++++++ tests/Composer/Test/Plugin/PluginInstallerTest.php | 4 ++-- 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index f8ca7f136..5c1bdc529 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -178,7 +178,7 @@ class Application extends BaseApplication foreach ($composer['scripts'] as $script => $dummy) { if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) { if ($this->has($script)) { - $io->writeError('A script named '.$script.' would override a native Composer function and has been skipped'); + $io->writeError('A script named '.$script.' would override a Composer command and has been skipped'); } else { $this->add(new Command\ScriptAliasCommand($script)); } @@ -195,7 +195,13 @@ class Application extends BaseApplication } if (!$input->hasParameterOption('--no-plugins')) { - $this->addCommands($this->getPluginCommands()); + foreach ($this->getPluginCommands() as $command) { + if ($this->has($command->getName())) { + $io->writeError('Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped'); + } else { + $this->add($command); + } + } } $result = parent::doRun($input, $output); @@ -395,7 +401,7 @@ class Application extends BaseApplication if (null !== $composer) { $pm = $composer->getPluginManager(); - foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider') as $capability) { + foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) { $newCommands = $capability->getCommands(); if (!is_array($newCommands)) { throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands'); diff --git a/src/Composer/Plugin/Capability/CommandProvider.php b/src/Composer/Plugin/Capability/CommandProvider.php index cb678a545..04a1b16b7 100644 --- a/src/Composer/Plugin/Capability/CommandProvider.php +++ b/src/Composer/Plugin/Capability/CommandProvider.php @@ -15,6 +15,11 @@ namespace Composer\Plugin\Capability; /** * Commands Provider Interface * + * This capability will receive an array with 'composer' and 'io' keys as + * constructor argument. Those contain Composer\Composer and Composer\IO\IOInterface + * instances. It also contains a 'plugin' key containing the plugin instance that + * created the capability. + * * @author Jérémy Derussé */ interface CommandProvider extends Capability diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 6c70fea7e..666bbce2a 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -362,6 +362,7 @@ class PluginManager throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist."); } + $ctorArgs['plugin'] = $plugin; $capabilityObj = new $capabilityClass($ctorArgs); // FIXME these could use is_a and do the check *before* instantiating once drop support for php<5.3.9 diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/CommandProvider.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/CommandProvider.php index 697a7c4e0..8c75a119a 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/CommandProvider.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/CommandProvider.php @@ -11,6 +11,15 @@ class CommandProvider implements CommandProvider { public function __construct(array $args) { + if (!$args['composer'] instanceof \Composer\Composer) { + throw new \RuntimeException('Expected a "composer" key'); + } + if (!$args['io'] instanceof \Composer\IO\IOInterface) { + throw new \RuntimeException('Expected an "io" key'); + } + if (!$args['plugin'] instanceof Plugin8) { + throw new \RuntimeException('Expected a "plugin" key with my own plugin'); + } } public function getCommands() @@ -28,6 +37,8 @@ class Command extends BaseCommand protected function execute(InputInterface $input, OutputInterface $output) { + $output->writeln('Executing'); + return 5; } } diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 524e3a551..6e98b192a 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -306,7 +306,7 @@ class PluginInstallerTest extends TestCase $installer = new PluginInstaller($this->io, $this->composer); $this->pm->loadInstalledPlugins(); - $caps = $this->pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider'); + $caps = $this->pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $this->composer, 'io' => $this->io)); $this->assertCount(1, $caps); $this->assertInstanceOf('Composer\Plugin\Capability\CommandProvider', $caps[0]); @@ -341,7 +341,7 @@ class PluginInstallerTest extends TestCase $this->assertInstanceOf($capabilityApi, $capability); $this->assertInstanceOf($capabilityImplementation, $capability); - $this->assertSame(array('a' => 1, 'b' => 2), $capability->args); + $this->assertSame(array('a' => 1, 'b' => 2, 'plugin' => $plugin), $capability->args); } public function invalidImplementationClassNames()