bug #20377 [Console] Fix infinite loop on missing input (chalasr)
This PR was merged into the 2.7 branch.
Discussion
----------
[Console] Fix infinite loop on missing input
| Q | A
| ------------- | ---
| Branch? | 2.7
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #20277
| License | MIT
| Doc PR | n/a
This fixes the infinite loop occurring when no input is provided for a question which has a validator and no max attempts (`null`), e.g. when using `SymfonyStyle::ask()` which automatically adds a validator.
Commits
-------
e64de1e
[Console] Fix infinite loop on missing input
This commit is contained in:
commit
74e65e1631
19
src/Symfony/Component/Console/Exception/RuntimeException.php
Normal file
19
src/Symfony/Component/Console/Exception/RuntimeException.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Console\Exception;
|
||||
|
||||
/**
|
||||
* @author Jérôme Tamarelle <jerome@tamarelle.net>
|
||||
*/
|
||||
class RuntimeException extends \RuntimeException
|
||||
{
|
||||
}
|
@ -17,6 +17,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* The QuestionHelper class provides helpers to interact with the user.
|
||||
@ -134,7 +135,7 @@ class QuestionHelper extends Helper
|
||||
if (false === $ret) {
|
||||
$ret = fgets($inputStream, 4096);
|
||||
if (false === $ret) {
|
||||
throw new \RuntimeException('Aborted');
|
||||
throw new RuntimeException('Aborted');
|
||||
}
|
||||
$ret = trim($ret);
|
||||
}
|
||||
@ -354,7 +355,7 @@ class QuestionHelper extends Helper
|
||||
shell_exec(sprintf('stty %s', $sttyMode));
|
||||
|
||||
if (false === $value) {
|
||||
throw new \RuntimeException('Aborted');
|
||||
throw new RuntimeException('Aborted');
|
||||
}
|
||||
|
||||
$value = trim($value);
|
||||
@ -372,7 +373,7 @@ class QuestionHelper extends Helper
|
||||
return $value;
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Unable to hide the response.');
|
||||
throw new RuntimeException('Unable to hide the response.');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -397,6 +398,8 @@ class QuestionHelper extends Helper
|
||||
|
||||
try {
|
||||
return call_user_func($question->getValidator(), $interviewer());
|
||||
} catch (RuntimeException $e) {
|
||||
throw $e;
|
||||
} catch (\Exception $error) {
|
||||
}
|
||||
}
|
||||
|
@ -402,6 +402,37 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase
|
||||
$dialog->ask($this->createInputInterfaceMock(), $output, $question);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Console\Exception\RuntimeException
|
||||
* @expectedExceptionMessage Aborted
|
||||
*/
|
||||
public function testAskThrowsExceptionOnMissingInput()
|
||||
{
|
||||
$dialog = new QuestionHelper();
|
||||
$dialog->setInputStream($this->getInputStream(''));
|
||||
|
||||
$dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), new Question('What\'s your name?'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Console\Exception\RuntimeException
|
||||
* @expectedExceptionMessage Aborted
|
||||
*/
|
||||
public function testAskThrowsExceptionOnMissingInputWithValidator()
|
||||
{
|
||||
$dialog = new QuestionHelper();
|
||||
$dialog->setInputStream($this->getInputStream(''));
|
||||
|
||||
$question = new Question('What\'s your name?');
|
||||
$question->setValidator(function () {
|
||||
if (!$value) {
|
||||
throw new \Exception('A value is required.');
|
||||
}
|
||||
});
|
||||
|
||||
$dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question);
|
||||
}
|
||||
|
||||
protected function getInputStream($input)
|
||||
{
|
||||
$stream = fopen('php://memory', 'r+', false);
|
||||
|
@ -101,6 +101,18 @@ class SymfonyQuestionHelperTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertOutputContains('Do you want a \?', $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Console\Exception\RuntimeException
|
||||
* @expectedExceptionMessage Aborted
|
||||
*/
|
||||
public function testAskThrowsExceptionOnMissingInput()
|
||||
{
|
||||
$dialog = new SymfonyQuestionHelper();
|
||||
|
||||
$dialog->setInputStream($this->getInputStream(''));
|
||||
$dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), new Question('What\'s your name?'));
|
||||
}
|
||||
|
||||
protected function getInputStream($input)
|
||||
{
|
||||
$stream = fopen('php://memory', 'r+', false);
|
||||
|
Reference in New Issue
Block a user