Skip to content

Commit

Permalink
Merge pull request #1 from consolidation/help-injection
Browse files Browse the repository at this point in the history
Inject option defaults from configuration into help.
  • Loading branch information
greg-1-anderson committed Jul 28, 2017
2 parents b30571a + 1509864 commit 3206544
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 4 deletions.
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -100,8 +100,9 @@ $config->import($processor->export());

The command option configuration feature described above in the section `Providing Command Options` is provided via a configuration injection class. All that you need to do to use this feature as attach this object to your Symfony Console application's event dispatcher:
```
$configInjector = new \Consolidation\Config\Inject\ConfigForCommand($config);
$application = new Symfony\Component\Console\Application($name, $version);
$configInjector = new \Consolidation\Config\Inject\ConfigForCommand($config);
$configInjector->setApplication($application);
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
$eventDispatcher->addSubscriber($configInjector);
Expand Down
10 changes: 10 additions & 0 deletions src/GlobalOptionDefaultValuesInterface.php
@@ -0,0 +1,10 @@
<?php
namespace Consolidation\Config;

interface GlobalOptionDefaultValuesInterface
{
/**
* Return an associative array of option-key => default-value
*/
public function getGlobalOptionDefaultValues();
}
44 changes: 44 additions & 0 deletions src/Inject/ConfigForCommand.php
Expand Up @@ -7,16 +7,23 @@
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Console\Application;

class ConfigForCommand implements EventSubscriberInterface
{
protected $config;
protected $application;

public function __construct(ConfigInterface $config)
{
$this->config = $config;
}

public function setApplication(Application $application)
{
$this->application = $application;
}

/**
* {@inheritdoc}
*/
Expand All @@ -35,6 +42,16 @@ public static function getSubscribedEvents()
public function injectConfiguration(ConsoleCommandEvent $event)
{
$command = $event->getCommand();
$this->injectConfigurationForCommand($command);

$targetOfHelpCommand = $this->getHelpCommandTarget($command, $event->getInput());
if ($targetOfHelpCommand) {
$this->injectConfigurationForCommand($targetOfHelpCommand);
}
}

protected function injectConfigurationForCommand($command)
{
$commandName = $command->getName();
$commandName = str_replace(':', '.', $commandName);
$definition = $command->getDefinition();
Expand All @@ -48,4 +65,31 @@ public function injectConfiguration(ConsoleCommandEvent $event)
}
}
}

protected function getHelpCommandTarget($command, $input)
{
if (($command->getName() != 'help') || (!isset($this->application))) {
return false;
}

// Symfony 3.x prepares $input for us; Symfony 2.x, on the other
// hand, passes it in prior to binding with the command definition,
// so we have to go to a little extra work. It may be inadvisable
// to do these steps for commands other than 'help'.
if (!$input->hasArgument('command_name')) {
$command->ignoreValidationErrors();
$command->mergeApplicationDefinition();
$input->bind($command->getDefinition());
}

// Symfony Console helpfully swaps 'command_name' and 'command'
// depending on whether the user entered `help foo` or `--help foo`.
// One of these is always `help`, and the other is the command we
// are actually interested in.
$nameOfCommandToDescribe = $input->getArgument('command_name');
if ($nameOfCommandToDescribe == 'help') {
$nameOfCommandToDescribe = $input->getArgument('command');
}
return $this->application->find($nameOfCommandToDescribe);
}
}
23 changes: 20 additions & 3 deletions tests/ConfigForCommandTest.php
Expand Up @@ -76,12 +76,29 @@ public function testInjectionWithOverride()
$this->assertEquals($expectedOutput, $output);
}

protected function runCommandViaApplication($command, $input)
public function testHelpDefaultInjection()
{
$configInjector = new ConfigForCommand($this->config);
$command = new MyFooCommand();
$input = new StringInput('help my:foo');

$output = new BufferedOutput();
list($status, $output) = $this->runCommandViaApplication($command, $input);

$expectedOutput = <<< EOT
What is the name of the thing we are naming [default: "baz"]
EOT;

$this->assertEquals(0, $status);
$this->assertContains($expectedOutput, $output);

}

protected function runCommandViaApplication($command, $input)
{
$application = new Application('TestApplication', '0.0.0');
$output = new BufferedOutput();

$configInjector = new ConfigForCommand($this->config);
$configInjector->setApplication($application);

$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
$eventDispatcher->addSubscriber($configInjector);
Expand Down

0 comments on commit 3206544

Please sign in to comment.