From 090295dbcb783dcbcc2dadcfd3a8539bb4ef8e71 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 28 Apr 2016 20:37:34 +0100 Subject: [PATCH] Adjust the CommandProvider to use plugin capabilities and test actual command creation, refs #3377 --- src/Composer/Console/Application.php | 15 ++++++--- .../CommandProvider.php} | 12 +++---- src/Composer/Plugin/PluginManager.php | 19 +++++++++++ .../Plugin/Fixtures/plugin-v5/composer.json | 13 -------- .../plugin-v8/Installer/CommandProvider.php | 33 +++++++++++++++++++ .../Fixtures/plugin-v8/Installer/Plugin8.php | 10 +++--- .../Plugin/Fixtures/plugin-v8/composer.json | 2 +- .../Test/Plugin/PluginInstallerTest.php | 18 ++++++++++ 8 files changed, 92 insertions(+), 30 deletions(-) rename src/Composer/Plugin/{CommandsProviderInterface.php => Capability/CommandProvider.php} (71%) create mode 100644 tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/CommandProvider.php diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index b21656558..f8ca7f136 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -27,7 +27,6 @@ use Composer\IO\IOInterface; use Composer\IO\ConsoleIO; use Composer\Json\JsonValidationException; use Composer\Util\ErrorHandler; -use Composer\Plugin\CommandsProviderInterface; /** * The console application that handles the commands @@ -395,10 +394,18 @@ class Application extends BaseApplication } if (null !== $composer) { - foreach ($composer->getPluginManager()->getPlugins() as $plugin) { - if ($plugin instanceof CommandsProviderInterface) { - $commands = array_merge($commands, $plugin->getCommands()); + $pm = $composer->getPluginManager(); + foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider') as $capability) { + $newCommands = $capability->getCommands(); + if (!is_array($newCommands)) { + throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands'); } + foreach ($newCommands as $command) { + if (!$command instanceof Command\BaseCommand) { + throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects'); + } + } + $commands = array_merge($commands, $newCommands); } } diff --git a/src/Composer/Plugin/CommandsProviderInterface.php b/src/Composer/Plugin/Capability/CommandProvider.php similarity index 71% rename from src/Composer/Plugin/CommandsProviderInterface.php rename to src/Composer/Plugin/Capability/CommandProvider.php index 4879b47fb..cb678a545 100644 --- a/src/Composer/Plugin/CommandsProviderInterface.php +++ b/src/Composer/Plugin/Capability/CommandProvider.php @@ -10,23 +10,19 @@ * file that was distributed with this source code. */ -namespace Composer\Plugin; - -use Composer\Composer; -use Composer\IO\IOInterface; +namespace Composer\Plugin\Capability; /** * Commands Provider Interface * * @author Jérémy Derussé */ -interface CommandsProviderInterface +interface CommandProvider extends Capability { - /** - * Retreives list of commands + * Retreives an array of commands * - * @return array + * @return Composer\Command\BaseCommand[] */ public function getCommands(); } diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index f807ed32e..6c70fea7e 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -374,4 +374,23 @@ class PluginManager return $capabilityObj; } } + + /** + * @param string $capabilityClassName The fully qualified name of the API interface which the plugin may provide + * an implementation of. + * @param array $ctorArgs Arguments passed to Capability's constructor. + * Keeping it an array will allow future values to be passed w\o changing the signature. + * @return Capability[] + */ + public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array()) + { + $capabilities = array(); + foreach ($this->getPlugins() as $plugin) { + if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) { + $capabilities[] = $capability; + } + } + + return $capabilities; + } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v5/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v5/composer.json index de263ebf2..7885cd6fd 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v5/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v5/composer.json @@ -1,6 +1,5 @@ { "name": "plugin-v5", -<<<<<<< HEAD "version": "1.0.0", "type": "composer-plugin", "autoload": { "psr-0": { "Installer": "" } }, @@ -9,17 +8,5 @@ }, "require": { "composer-plugin-api": "*" -======= - "version": "5.0.0", - "type": "composer-plugin", - "autoload": { "psr-0": { "Installer": "" } }, - "extra": { - "class": [ - "Installer\\Plugin" - ] - }, - "require": { - "composer-plugin-api": "1.0.0" ->>>>>>> jderusse/plugin-with-commands } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/CommandProvider.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/CommandProvider.php new file mode 100644 index 000000000..697a7c4e0 --- /dev/null +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/CommandProvider.php @@ -0,0 +1,33 @@ +setName('custom-plugin-command'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + return 5; + } +} diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/Plugin8.php b/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/Plugin8.php index aeb231f6d..7e9a0aab1 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/Plugin8.php +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v8/Installer/Plugin8.php @@ -5,9 +5,9 @@ namespace Installer; use Composer\Composer; use Composer\IO\IOInterface; use Composer\Plugin\PluginInterface; -use Composer\Plugin\CommandsProviderInterface; +use Composer\Plugin\Capable; -class Plugin8 implements PluginInterface, CommandsProviderInterface +class Plugin8 implements PluginInterface, Capable { public $version = 'installer-v8'; @@ -15,8 +15,10 @@ class Plugin8 implements PluginInterface, CommandsProviderInterface { } - public function getCommands() + public function getCapabilities() { - return null; + return array( + 'Composer\Plugin\Capability\CommandProvider' => 'Installer\CommandProvider', + ); } } diff --git a/tests/Composer/Test/Plugin/Fixtures/plugin-v8/composer.json b/tests/Composer/Test/Plugin/Fixtures/plugin-v8/composer.json index b3cd990e4..799df2e61 100644 --- a/tests/Composer/Test/Plugin/Fixtures/plugin-v8/composer.json +++ b/tests/Composer/Test/Plugin/Fixtures/plugin-v8/composer.json @@ -9,6 +9,6 @@ ] }, "require": { - "composer-plugin-api": "1.0.0" + "composer-plugin-api": "1.1.0" } } diff --git a/tests/Composer/Test/Plugin/PluginInstallerTest.php b/tests/Composer/Test/Plugin/PluginInstallerTest.php index 80e674fda..524e3a551 100644 --- a/tests/Composer/Test/Plugin/PluginInstallerTest.php +++ b/tests/Composer/Test/Plugin/PluginInstallerTest.php @@ -297,6 +297,24 @@ class PluginInstallerTest extends TestCase $this->assertCount(0, $this->pm->getPlugins()); } + public function testCommandProviderCapability() + { + $this->repository + ->expects($this->exactly(2)) + ->method('getPackages') + ->will($this->returnValue(array($this->packages[7]))); + $installer = new PluginInstaller($this->io, $this->composer); + $this->pm->loadInstalledPlugins(); + + $caps = $this->pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider'); + $this->assertCount(1, $caps); + $this->assertInstanceOf('Composer\Plugin\Capability\CommandProvider', $caps[0]); + + $commands = $caps[0]->getCommands(); + $this->assertCount(1, $commands); + $this->assertInstanceOf('Composer\Command\BaseCommand', $commands[0]); + } + public function testIncapablePluginIsCorrectlyDetected() { $plugin = $this->getMockBuilder('Composer\Plugin\PluginInterface')