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

Commit c3ac277

Browse filesBrowse files
committed
[Console] Fix BC break regarding console.command event
1 parent 25a2ce0 commit c3ac277
Copy full SHA for c3ac277

File tree

3 files changed

+143
-3
lines changed
Filter options

3 files changed

+143
-3
lines changed

‎src/Symfony/Component/Console/Application.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Application.php
+20-3Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Console\Descriptor\TextDescriptor;
1515
use Symfony\Component\Console\Descriptor\XmlDescriptor;
16+
use Symfony\Component\Console\Event\InputDecorator;
1617
use Symfony\Component\Console\Exception\ExceptionInterface;
1718
use Symfony\Component\Console\Helper\DebugFormatterHelper;
1819
use Symfony\Component\Console\Helper\ProcessHelper;
@@ -859,13 +860,29 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
859860
// ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
860861
}
861862

863+
$event = new ConsoleCommandEvent($command, $input, $output);
864+
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
865+
866+
// bind again after the console.command event to parse newly added arguments/options
867+
try {
868+
$input->bind($command->getDefinition());
869+
} catch (ExceptionInterface $e) {
870+
// ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
871+
}
872+
862873
// don't bind the input again as it would override any input argument/option set from the command event in
863874
// addition to being useless
864875
$command->setInputBound(true);
865876

866-
$event = new ConsoleCommandEvent($command, $input, $output);
867-
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
868-
877+
$inputDecorator = $event->getInput();
878+
if ($inputDecorator instanceof InputDecorator) {
879+
foreach ($inputDecorator->getOverriddenArguments() as $k => $v) {
880+
$input->setArgument($k, $v);
881+
}
882+
foreach ($inputDecorator->getOverriddenOptions() as $k => $v) {
883+
$input->setOption($k, $v);
884+
}
885+
}
869886
if ($event->commandShouldRun()) {
870887
try {
871888
$e = null;

‎src/Symfony/Component/Console/Event/ConsoleCommandEvent.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Event/ConsoleCommandEvent.php
+72Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
namespace Symfony\Component\Console\Event;
1313

14+
use Symfony\Component\Console\Input\Input;
15+
use Symfony\Component\Console\Input\InputInterface;
16+
1417
/**
1518
* Allows to do things before the command is executed, like skipping the command or changing the input.
1619
*
@@ -23,6 +26,11 @@ class ConsoleCommandEvent extends ConsoleEvent
2326
*/
2427
const RETURN_CODE_DISABLED = 113;
2528

29+
/**
30+
* @internal
31+
*/
32+
private $inputDecorator;
33+
2634
/**
2735
* Indicates if the command should be run or skipped.
2836
*
@@ -59,4 +67,68 @@ public function commandShouldRun()
5967
{
6068
return $this->commandShouldRun;
6169
}
70+
71+
/**
72+
* {@inheritdoc}
73+
*/
74+
public function getInput()
75+
{
76+
if ($this->inputDecorator) {
77+
return $this->inputDecorator;
78+
}
79+
80+
return $this->inputDecorator = new InputDecorator(parent::getInput());
81+
}
82+
}
83+
84+
/**
85+
* @internal
86+
*/
87+
final class InputDecorator
88+
{
89+
private $inner;
90+
private $overriddenArguments = array();
91+
private $overriddenOptions = array();
92+
93+
public function __construct(InputInterface $inner)
94+
{
95+
$this->inner = $inner;
96+
}
97+
98+
public function __call($method, $arguments)
99+
{
100+
if ('setArgument' === $method) {
101+
return $this->setArgument($arguments[0], $arguments[1]);
102+
}
103+
104+
if ('setOption' === $method) {
105+
return $this->setOption($arguments[0], $arguments[1]);
106+
}
107+
108+
return call_user_func_array(array($this->inner, $method), $arguments);
109+
}
110+
111+
public function setArgument($key, $value)
112+
{
113+
$this->overriddenArguments[$key] = $value;
114+
115+
return $this->inner->setArgument($key, $value);
116+
}
117+
118+
public function setOption($key, $value)
119+
{
120+
$this->overriddenOptions[$key] = $value;
121+
122+
return $this->inner->setOption($key, $value);
123+
}
124+
125+
public function getOverriddenArguments()
126+
{
127+
return $this->overriddenArguments;
128+
}
129+
130+
public function getOverriddenOptions()
131+
{
132+
return $this->overriddenOptions;
133+
}
62134
}

‎src/Symfony/Component/Console/Tests/ApplicationTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Tests/ApplicationTest.php
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,57 @@ public function testUpdateInputFromConsoleCommandEvent()
11381138
$this->assertEquals('overriden', $tester->getInput()->getOption('extra'));
11391139
}
11401140

1141+
public function testAddArgumentFromConsoleCommandEvent()
1142+
{
1143+
$dispatcher = $this->getDispatcher();
1144+
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
1145+
$event->getCommand()->addArgument('extra', InputArgument::REQUIRED);
1146+
});
1147+
1148+
$application = new Application();
1149+
$application->setDispatcher($dispatcher);
1150+
$application->setAutoExit(false);
1151+
1152+
$application
1153+
->register('foo')
1154+
->addOption('extra', null, InputOption::VALUE_REQUIRED)
1155+
->setCode(function (InputInterface $input, OutputInterface $output) {
1156+
$output->write('foo.');
1157+
})
1158+
;
1159+
1160+
$tester = new ApplicationTester($application);
1161+
$tester->run(array('command' => 'foo', 'extra' => 'foo'));
1162+
1163+
$this->assertEquals('foo', $tester->getInput()->getArgument('extra'));
1164+
}
1165+
1166+
public function testAddAndSetArgumentFromConsoleCommandEvent()
1167+
{
1168+
$dispatcher = $this->getDispatcher();
1169+
$dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
1170+
$event->getCommand()->addArgument('extra', InputArgument::REQUIRED);
1171+
$event->getInput()->setArgument('extra', 'overridden');
1172+
});
1173+
1174+
$application = new Application();
1175+
$application->setDispatcher($dispatcher);
1176+
$application->setAutoExit(false);
1177+
1178+
$application
1179+
->register('foo')
1180+
->addOption('extra', null, InputOption::VALUE_REQUIRED)
1181+
->setCode(function (InputInterface $input, OutputInterface $output) {
1182+
$output->write('foo.');
1183+
})
1184+
;
1185+
1186+
$tester = new ApplicationTester($application);
1187+
$tester->run(array('command' => 'foo'));
1188+
1189+
$this->assertSame('overridden', $tester->getInput()->getArgument('extra'));
1190+
}
1191+
11411192
public function testTerminalDimensions()
11421193
{
11431194
$application = new Application();

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.