Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 99f8d85

Browse files
committed
bug #24929 [Console] Fix traversable autocomplete values (ro0NL)
This PR was merged into the 2.7 branch. Discussion ---------- [Console] Fix traversable autocomplete values | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #... <!-- #-prefixed issue number(s), if any --> | License | MIT | Doc PR | symfony/symfony-docs#... <!--highly recommended for new features--> `Question::setAutocompleterValues` implies passing a `\Traversable` value is allowed, yet it doesnt work :) It also restricts the traversable to be countable, which is not really needed (blocking pure API / iterable type as of 4.0). Commits ------- 965b5b5 [Console] Fix traversable autocomplete values
2 parents cf78277 + 965b5b5 commit 99f8d85

File tree

3 files changed

+54
-7
lines changed

3 files changed

+54
-7
lines changed

src/Symfony/Component/Console/Helper/QuestionHelper.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ public function doAsk(OutputInterface $output, Question $question)
134134
$ret = trim($ret);
135135
}
136136
} else {
137-
$ret = trim($this->autocomplete($output, $question, $inputStream));
137+
$ret = trim($this->autocomplete($output, $question, $inputStream, is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false)));
138138
}
139139

140140
$ret = strlen($ret) > 0 ? $ret : $question->getDefault();
@@ -190,12 +190,12 @@ protected function writeError(OutputInterface $output, \Exception $error)
190190
* @param OutputInterface $output
191191
* @param Question $question
192192
* @param resource $inputStream
193+
* @param array $autocomplete
193194
*
194195
* @return string
195196
*/
196-
private function autocomplete(OutputInterface $output, Question $question, $inputStream)
197+
private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete)
197198
{
198-
$autocomplete = $question->getAutocompleterValues();
199199
$ret = '';
200200

201201
$i = 0;

src/Symfony/Component/Console/Question/Question.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,8 @@ public function setAutocompleterValues($values)
137137
$values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
138138
}
139139

140-
if (null !== $values && !is_array($values)) {
141-
if (!$values instanceof \Traversable || !$values instanceof \Countable) {
142-
throw new \InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
143-
}
140+
if (null !== $values && !is_array($values) && !$values instanceof \Traversable) {
141+
throw new \InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.');
144142
}
145143

146144
if ($this->hidden) {

src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,40 @@ public function testEmptyChoices()
514514
new ChoiceQuestion('Question', array(), 'irrelevant');
515515
}
516516

517+
public function testTraversableAutocomplete()
518+
{
519+
if (!$this->hasSttyAvailable()) {
520+
$this->markTestSkipped('`stty` is required to test autocomplete functionality');
521+
}
522+
523+
// Acm<NEWLINE>
524+
// Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE>
525+
// <NEWLINE>
526+
// <UP ARROW><UP ARROW><NEWLINE>
527+
// <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE>
528+
// <DOWN ARROW><NEWLINE>
529+
// S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE>
530+
// F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE>
531+
$inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n");
532+
533+
$dialog = new QuestionHelper();
534+
$dialog->setInputStream($inputStream);
535+
$helperSet = new HelperSet(array(new FormatterHelper()));
536+
$dialog->setHelperSet($helperSet);
537+
538+
$question = new Question('Please select a bundle', 'FrameworkBundle');
539+
$question->setAutocompleterValues(new AutocompleteValues(array('irrelevant' => 'AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle')));
540+
541+
$this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
542+
$this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
543+
$this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
544+
$this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
545+
$this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
546+
$this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
547+
$this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
548+
$this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question));
549+
}
550+
517551
protected function getInputStream($input)
518552
{
519553
$stream = fopen('php://memory', 'r+', false);
@@ -545,3 +579,18 @@ private function hasSttyAvailable()
545579
return 0 === $exitcode;
546580
}
547581
}
582+
583+
class AutocompleteValues implements \IteratorAggregate
584+
{
585+
private $values;
586+
587+
public function __construct(array $values)
588+
{
589+
$this->values = $values;
590+
}
591+
592+
public function getIterator()
593+
{
594+
return new \ArrayIterator($this->values);
595+
}
596+
}

0 commit comments

Comments
 (0)