Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Console] Fix BC break regarding console.command event #21953

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[Console] Fix BC break regarding console.command event
  • Loading branch information
chalasr committed Mar 14, 2017
commit 3d183c440c4e22f43df7c145c02019294eba52b7
30 changes: 25 additions & 5 deletions 30 src/Symfony/Component/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Event\InputDecorator;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Helper\DebugFormatterHelper;
use Symfony\Component\Console\Helper\ProcessHelper;
Expand Down Expand Up @@ -859,13 +860,32 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
// ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
}

// don't bind the input again as it would override any input argument/option set from the command event in
// addition to being useless
$command->setInputBound(true);

$event = new ConsoleCommandEvent($command, $input, $output);
$event = new ConsoleCommandEvent($command, $eventInput = new InputDecorator($input), $output);
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);

$overriddenArguments = $eventInput->getOverriddenArguments();
$overriddenOptions = $eventInput->getOverriddenOptions();

if ($overriddenArguments || $overriddenOptions) {
// bind again after the console.command event to parse newly added arguments/options
try {
$input->bind($command->getDefinition());
} catch (ExceptionInterface $e) {
}

// mark the input as bound to prevent binding it again as it would squash any input argument/option set
// from the command event
$command->setInputBound(true);

foreach ($overriddenArguments as $k => $v) {
$input->setArgument($k, $v);
}

foreach ($overriddenOptions as $k => $v) {
$input->setOption($k, $v);
}
}

if ($event->commandShouldRun()) {
try {
$e = null;
Expand Down
107 changes: 107 additions & 0 deletions 107 src/Symfony/Component/Console/Event/ConsoleCommandEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;

/**
* Allows to do things before the command is executed, like skipping the command or changing the input.
*
Expand Down Expand Up @@ -60,3 +63,107 @@ public function commandShouldRun()
return $this->commandShouldRun;
}
}

/**
* @internal
*/
final class InputDecorator implements InputInterface
{
private $inner;
private $overriddenArguments = array();
private $overriddenOptions = array();

public function __construct(InputInterface $inner)
{
$this->inner = $inner;
}

public function setArgument($key, $value)
{
$this->overriddenArguments[$key] = $value;

return $this->inner->setArgument($key, $value);
}

public function setOption($key, $value)
{
$this->overriddenOptions[$key] = $value;

return $this->inner->setOption($key, $value);
}

public function getOverriddenArguments()
{
return $this->overriddenArguments;
}

public function getOverriddenOptions()
{
return $this->overriddenOptions;
}

public function getFirstArgument()
{
return $this->inner->getFirstArgument();
}

public function hasParameterOption($values)
{
return $this->inner->hasParameterOption($values);
}

public function getParameterOption($values, $default = false)
{
return $this->inner->getParameterOption($values, $default);
}

public function bind(InputDefinition $definition)
{
return $this->inner->bind($definition);
}

public function validate()
{
return $this->inner->validate();
}

public function getArguments()
{
return $this->inner->getArguments();
}

public function getArgument($name)
{
return $this->inner->getArgument($name);
}

public function hasArgument($name)
{
return $this->inner->hasArgument($name);
}

public function getOptions()
{
return $this->inner->getOptions();
}

public function getOption($name)
{
return $this->inner->getOption($name);
}

public function hasOption($name)
{
return $this->inner->hasOption($name);
}

public function isInteractive()
{
return $this->inner->isInteractive();
}

public function setInteractive($interactive)
{
return $this->inner->setInteractive($interactive);
}
}
51 changes: 51 additions & 0 deletions 51 src/Symfony/Component/Console/Tests/ApplicationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,57 @@ public function testUpdateInputFromConsoleCommandEvent()
$this->assertEquals('overriden', $tester->getInput()->getOption('extra'));
}

public function testAddArgumentFromConsoleCommandEvent()
{
$dispatcher = $this->getDispatcher();
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
$event->getCommand()->addArgument('extra', InputArgument::REQUIRED);
});

$application = new Application();
$application->setDispatcher($dispatcher);
$application->setAutoExit(false);

$application
->register('foo')
->addOption('extra', null, InputOption::VALUE_REQUIRED)
->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('foo.');
})
;

$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo', 'extra' => 'foo'));

$this->assertEquals('foo', $tester->getInput()->getArgument('extra'));
}

public function testAddAndSetArgumentFromConsoleCommandEvent()
{
$dispatcher = $this->getDispatcher();
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
$event->getCommand()->addArgument('extra', InputArgument::REQUIRED);
$event->getInput()->setArgument('extra', 'overridden');
});

$application = new Application();
$application->setDispatcher($dispatcher);
$application->setAutoExit(false);

$application
->register('foo')
->addOption('extra', null, InputOption::VALUE_REQUIRED)
->setCode(function (InputInterface $input, OutputInterface $output) {
$output->write('foo.');
})
;

$tester = new ApplicationTester($application);
$tester->run(array('command' => 'foo'));

$this->assertSame('overridden', $tester->getInput()->getArgument('extra'));
}

public function testTerminalDimensions()
{
$application = new Application();
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.