feature #15938 [Console] Bind input before executing the COMMAND event (WouterJ)
This PR was merged into the 2.8 branch.
Discussion
----------
[Console] Bind input before executing the COMMAND event
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #10695 (problem 1)
| License | MIT
| Doc PR | -
Previously, `$input` wasn't very usefull in the `console.command` event, as the input was not yet bound to the command definition.
With this PR, the input is now bound twice: Once before the event is dispatched (to make it usefull in the listeners) and once at the original location in `Command#run()` (to allow changing the input definition in an event listener).
Commits
-------
0af1676
Bind input before executing the COMMAND event
This commit is contained in:
commit
3b3431e289
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Console;
|
|||
|
||||
use Symfony\Component\Console\Descriptor\TextDescriptor;
|
||||
use Symfony\Component\Console\Descriptor\XmlDescriptor;
|
||||
use Symfony\Component\Console\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Console\Helper\DebugFormatterHelper;
|
||||
use Symfony\Component\Console\Helper\ProcessHelper;
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
|
@ -840,6 +841,14 @@ class Application
|
|||
return $command->run($input, $output);
|
||||
}
|
||||
|
||||
// bind before the console.command event, so the listeners have access to input options/arguments
|
||||
try {
|
||||
$command->mergeApplicationDefinition();
|
||||
$input->bind($command->getDefinition());
|
||||
} catch (ExceptionInterface $e) {
|
||||
// ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
|
||||
}
|
||||
|
||||
$event = new ConsoleCommandEvent($command, $input, $output);
|
||||
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Console\Command;
|
|||
|
||||
use Symfony\Component\Console\Descriptor\TextDescriptor;
|
||||
use Symfony\Component\Console\Descriptor\XmlDescriptor;
|
||||
use Symfony\Component\Console\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
|
@ -221,7 +222,7 @@ class Command
|
|||
// bind the input against the command specific arguments/options
|
||||
try {
|
||||
$input->bind($this->definition);
|
||||
} catch (\Exception $e) {
|
||||
} catch (ExceptionInterface $e) {
|
||||
if (!$this->ignoreValidationErrors) {
|
||||
throw $e;
|
||||
}
|
||||
|
|
|
@ -946,6 +946,63 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $exitCode);
|
||||
}
|
||||
|
||||
public function testRunWithDispatcherAccessingInputOptions()
|
||||
{
|
||||
$noInteractionValue = null;
|
||||
$quietValue = null;
|
||||
|
||||
$dispatcher = $this->getDispatcher();
|
||||
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$noInteractionValue, &$quietValue) {
|
||||
$input = $event->getInput();
|
||||
|
||||
$noInteractionValue = $input->getOption('no-interaction');
|
||||
$quietValue = $input->getOption('quiet');
|
||||
});
|
||||
|
||||
$application = new Application();
|
||||
$application->setDispatcher($dispatcher);
|
||||
$application->setAutoExit(false);
|
||||
|
||||
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
|
||||
$output->write('foo.');
|
||||
});
|
||||
|
||||
$tester = new ApplicationTester($application);
|
||||
$tester->run(array('command' => 'foo', '--no-interaction' => true));
|
||||
|
||||
$this->assertTrue($noInteractionValue);
|
||||
$this->assertFalse($quietValue);
|
||||
}
|
||||
|
||||
public function testRunWithDispatcherAddingInputOptions()
|
||||
{
|
||||
$extraValue = null;
|
||||
|
||||
$dispatcher = $this->getDispatcher();
|
||||
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$extraValue) {
|
||||
$definition = $event->getCommand()->getDefinition();
|
||||
$input = $event->getInput();
|
||||
|
||||
$definition->addOption(new InputOption('extra', null, InputOption::VALUE_REQUIRED));
|
||||
$input->bind($definition);
|
||||
|
||||
$extraValue = $input->getOption('extra');
|
||||
});
|
||||
|
||||
$application = new Application();
|
||||
$application->setDispatcher($dispatcher);
|
||||
$application->setAutoExit(false);
|
||||
|
||||
$application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
|
||||
$output->write('foo.');
|
||||
});
|
||||
|
||||
$tester = new ApplicationTester($application);
|
||||
$tester->run(array('command' => 'foo', '--extra' => 'some test value'));
|
||||
|
||||
$this->assertEquals('some test value', $extraValue);
|
||||
}
|
||||
|
||||
public function testTerminalDimensions()
|
||||
{
|
||||
$application = new Application();
|
||||
|
|
Reference in New Issue