Skip to content
This repository has been archived by the owner on Sep 5, 2020. It is now read-only.

Commit

Permalink
Change plugins configuration publishing flow
Browse files Browse the repository at this point in the history
  • Loading branch information
Anahkiasen committed Aug 5, 2016
1 parent 6ad1277 commit 17c62d2
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 51 deletions.
2 changes: 1 addition & 1 deletion src/Rocketeer/Binaries/AbstractBinary.php
Expand Up @@ -230,7 +230,7 @@ protected function buildEnvironmentVariables($env)
{
$variables = '';
foreach ($env as $key => $value) {
$variables .= $key.'='.$value. ' ';
$variables .= $key.'='.$value.' ';
}

return trim($variables);
Expand Down
19 changes: 14 additions & 5 deletions src/Rocketeer/Console/Commands/Plugins/PublishCommand.php
Expand Up @@ -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.
Expand Down Expand Up @@ -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'));
}

/**
Expand All @@ -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'],
];
}
}
Expand Up @@ -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
{
Expand Down
6 changes: 6 additions & 0 deletions src/Rocketeer/Services/Filesystem/FilesystemInterface.php
Expand Up @@ -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);
}
105 changes: 79 additions & 26 deletions src/Rocketeer/Services/Ignition/PluginsIgniter.php
Expand Up @@ -12,6 +12,7 @@

namespace Rocketeer\Services\Ignition;

use ReflectionClass;
use Rocketeer\Traits\ContainerAwareTrait;

/**
Expand All @@ -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 <comment>'.str_replace($this->paths->getBasePath(), null, $fileDestination).'</comment>');
}
}

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// HELPERS ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/**
* Find all the possible locations for a package's configuration.
*
Expand Down Expand Up @@ -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 <comment>' .str_replace($this->paths->getBasePath(), null, $fileDestination). '</comment>');
}

return $packages;
}
}
6 changes: 3 additions & 3 deletions tests/Console/Commands/PublishCommandTest.php
Expand Up @@ -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', '<?php return ["foo" => "bar"]');
$this->files->put($path.'/rocketeer-slack.php', '<?php return ["foo" => "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');
}
}
16 changes: 1 addition & 15 deletions tests/Services/Ignition/PluginsIgniterTest.php
Expand Up @@ -35,28 +35,14 @@ 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);

$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');
}
Expand Down

0 comments on commit 17c62d2

Please sign in to comment.