From 17c62d2ade2de14fffeb89b076812b19a3bd7ee1 Mon Sep 17 00:00:00 2001 From: Maxime Fabre Date: Fri, 5 Aug 2016 17:08:00 +0200 Subject: [PATCH] Change plugins configuration publishing flow --- src/Rocketeer/Binaries/AbstractBinary.php | 2 +- .../Commands/Plugins/PublishCommand.php | 19 +++- .../Listeners/TaggableListenerInterface.php | 2 +- .../Filesystem/FilesystemInterface.php | 6 + .../Services/Ignition/PluginsIgniter.php | 105 +++++++++++++----- tests/Console/Commands/PublishCommandTest.php | 6 +- .../Services/Ignition/PluginsIgniterTest.php | 16 +-- 7 files changed, 105 insertions(+), 51 deletions(-) diff --git a/src/Rocketeer/Binaries/AbstractBinary.php b/src/Rocketeer/Binaries/AbstractBinary.php index 8f9b87d4e..efb06ab34 100644 --- a/src/Rocketeer/Binaries/AbstractBinary.php +++ b/src/Rocketeer/Binaries/AbstractBinary.php @@ -230,7 +230,7 @@ protected function buildEnvironmentVariables($env) { $variables = ''; foreach ($env as $key => $value) { - $variables .= $key.'='.$value. ' '; + $variables .= $key.'='.$value.' '; } return trim($variables); diff --git a/src/Rocketeer/Console/Commands/Plugins/PublishCommand.php b/src/Rocketeer/Console/Commands/Plugins/PublishCommand.php index 1c346df25..7ecfc536a 100644 --- a/src/Rocketeer/Console/Commands/Plugins/PublishCommand.php +++ b/src/Rocketeer/Console/Commands/Plugins/PublishCommand.php @@ -15,6 +15,7 @@ use Rocketeer\Console\Commands\AbstractCommand; use Rocketeer\Services\Ignition\PluginsIgniter; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; /** * Publishes the configuration of a plugin. @@ -50,11 +51,9 @@ public function fire() { $this->container->add('command', $this); - /** @var string $package */ - $package = $this->argument('package'); - $publisher = new PluginsIgniter($this->container); - $publisher->publish($package); + $publisher->setForce($this->option('force')); + $publisher->publish($this->argument('package')); } /** @@ -65,7 +64,17 @@ public function fire() protected function getArguments() { return [ - ['package', InputArgument::REQUIRED, 'The package to publish the configuration for'], + ['package', InputArgument::IS_ARRAY, 'The package to publish the configuration for'], + ]; + } + + /** + * @return array + */ + protected function getOptions() + { + return [ + ['force', 'F', InputOption::VALUE_NONE, 'Force overwriting already published configurations'], ]; } } diff --git a/src/Rocketeer/Services/Events/Listeners/TaggableListenerInterface.php b/src/Rocketeer/Services/Events/Listeners/TaggableListenerInterface.php index 632eff8af..0256c3ade 100644 --- a/src/Rocketeer/Services/Events/Listeners/TaggableListenerInterface.php +++ b/src/Rocketeer/Services/Events/Listeners/TaggableListenerInterface.php @@ -15,7 +15,7 @@ use League\Event\ListenerInterface; /** - * Interface for listeners that can be assigned a tag + * Interface for listeners that can be assigned a tag. */ interface TaggableListenerInterface extends ListenerInterface { diff --git a/src/Rocketeer/Services/Filesystem/FilesystemInterface.php b/src/Rocketeer/Services/Filesystem/FilesystemInterface.php index 4a55c463e..2ffc7e1d2 100644 --- a/src/Rocketeer/Services/Filesystem/FilesystemInterface.php +++ b/src/Rocketeer/Services/Filesystem/FilesystemInterface.php @@ -46,4 +46,10 @@ public function includeFile($path); * @param bool $overwrite */ public function copyDir($from, $to, $overwrite = false); + + /** + * @param string $path + * @param string $newpath + */ + public function forceCopy($path, $newpath); } diff --git a/src/Rocketeer/Services/Ignition/PluginsIgniter.php b/src/Rocketeer/Services/Ignition/PluginsIgniter.php index 19c64ec3f..8bb323900 100644 --- a/src/Rocketeer/Services/Ignition/PluginsIgniter.php +++ b/src/Rocketeer/Services/Ignition/PluginsIgniter.php @@ -12,6 +12,7 @@ namespace Rocketeer\Services\Ignition; +use ReflectionClass; use Rocketeer\Traits\ContainerAwareTrait; /** @@ -21,28 +22,78 @@ class PluginsIgniter { use ContainerAwareTrait; + /** + * @var bool + */ + protected $force = false; + + /** + * @param bool $force + */ + public function setForce($force) + { + $this->force = $force; + } + + //////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////// PUBLISHING ////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /** * Publishes a package's configuration. * - * @param string $package + * @param string|string[] $plugins * * @return bool|string|null */ - public function publish($package) + public function publish($plugins = null) { - // Find the plugin's configuration - $paths = $this->findPackageConfiguration($package); - - // Cancel if no valid paths - $paths = array_filter($paths, [$this->files, 'isDirectory']); - $paths = array_values($paths); - if (empty($paths)) { - return $this->explainer->error('No configuration found for '.$package); + $plugins = $this->gatherLoadedPackagesHandles($plugins); + foreach ($plugins as $plugin) { + // Find the plugin's configuration + $paths = $this->findPackageConfiguration($plugin); + + // Cancel if no valid paths + $paths = array_filter($paths, [$this->files, 'isDirectory']); + $paths = array_values($paths); + if (empty($paths)) { + $this->explainer->comment('No configuration found for '.$plugin); + continue; + } + + $this->publishConfiguration($paths[0]); } + } + + /** + * Publishes a configuration within a classic application. + * + * @param string $path + * + * @return bool + */ + protected function publishConfiguration($path) + { + // Compute and create the destination folder + $destination = $this->paths->getConfigurationPath().'/plugins'; - return $this->publishConfiguration($paths[0]); + // Export configuration + $files = $this->files->listFiles($path, true); + foreach ($files as $file) { + $fileDestination = $destination.DS.$file['basename']; + if ($this->files->has($destination) && !$this->force) { + continue; + } + + $this->files->forceCopy($file['path'], $fileDestination); + $this->explainer->success('Published '.str_replace($this->paths->getBasePath(), null, $fileDestination).''); + } } + //////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////// HELPERS //////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + /** * Find all the possible locations for a package's configuration. * @@ -70,27 +121,29 @@ public function findPackageConfiguration($package) } /** - * Publishes a configuration within a classic application. + * Infer the name of the loaded packages + * from their service provider. * - * @param string $path + * @param string|string[] $packages * - * @return bool + * @return string[] */ - protected function publishConfiguration($path) + protected function gatherLoadedPackagesHandles($packages) { - // Compute and create the destination folder - $destination = $this->paths->getConfigurationPath().'/plugins'; + $packages = (array) $packages; + if (!$packages) { + $plugins = $this->container->getPlugins(); + foreach ($plugins as $plugin) { + $path = (new ReflectionClass($plugin))->getFileName(); + preg_match('/vendor\/([^\/]+)\/([^\/]+)/', $path, $handle); + if (count($handle) !== 3) { + continue; + } - // Export configuration - $files = $this->files->listFiles($path, true); - foreach ($files as $file) { - $fileDestination = $destination.DS.$file['basename']; - if ($this->files->has($destination) && !$this->command->confirm('File '.$file['basename'].' already exists, replace?')) { - continue; + $packages[] = $handle[1].'/'.$handle[2]; } - - $this->files->forceCopy($file['path'], $fileDestination); - $this->command->writeln('Published ' .str_replace($this->paths->getBasePath(), null, $fileDestination). ''); } + + return $packages; } } diff --git a/tests/Console/Commands/PublishCommandTest.php b/tests/Console/Commands/PublishCommandTest.php index 82f8b5685..ef256083f 100644 --- a/tests/Console/Commands/PublishCommandTest.php +++ b/tests/Console/Commands/PublishCommandTest.php @@ -27,10 +27,10 @@ public function testCanFlushLocalStorage() public function testCanExportConfiguration() { $path = $this->paths->getRocketeerPath().'/vendor/anahkiasen/rocketeer-slack/config'; - $this->files->put($path.'/foo.php', ' "bar"]'); + $this->files->put($path.'/rocketeer-slack.php', ' "bar"]'); $tester = $this->executeCommand('plugins:config', ['package' => 'anahkiasen/rocketeer-slack']); - $this->assertContains('Published configuration from', $tester->getDisplay()); - $this->assertVirtualFileExists($this->paths->getRocketeerPath().'/config/plugins/rocketeer-slack/foo.php'); + $this->assertContains('Published', $tester->getDisplay()); + $this->assertVirtualFileExists($this->paths->getRocketeerPath().'/config/plugins/rocketeer-slack.php'); } } diff --git a/tests/Services/Ignition/PluginsIgniterTest.php b/tests/Services/Ignition/PluginsIgniterTest.php index e73eac3f5..bc5a68ab9 100644 --- a/tests/Services/Ignition/PluginsIgniterTest.php +++ b/tests/Services/Ignition/PluginsIgniterTest.php @@ -35,20 +35,6 @@ public function setUp() $this->from = $this->container->get('path.base').'/vendor/anahkiasen/rocketeer-slack/src/config'; } - public function testCanPublishPluginConfiguration() - { - $this->usesLaravel(false); - - $destination = $this->paths->getConfigurationPath().'/plugins/rocketeer-slack'; - $prophecy = $this->bindFilesystemProphecy(); - $prophecy->has(Argument::cetera())->willReturn(true); - $prophecy->has($destination)->willReturn(false); - $prophecy->isDirectory(Argument::cetera())->shouldBeCalled()->willReturn(true); - $prophecy->copyDir($this->from, $destination)->shouldBeCalled()->willReturn(true); - - $this->plugins->publish('anahkiasen/rocketeer-slack'); - } - public function testCancelsIfNoValidConfigurationPath() { $this->usesLaravel(false); @@ -56,7 +42,7 @@ public function testCancelsIfNoValidConfigurationPath() $prophecy = $this->bindFilesystemProphecy(); $prophecy->isDirectory(Argument::cetera())->willReturn(false); $prophecy->has(Argument::cetera())->willReturn(false); - $prophecy->createDir(Argument::any())->shouldNotBeCalled(); + $prophecy->forceCopy(Argument::any())->shouldNotBeCalled(); $this->plugins->publish('anahkiasen/rocketeer-slack'); }