From e64de1eac65779f1aa3c9c9c4203ea2e64558907 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 1 Nov 2016 20:56:21 +0100 Subject: [PATCH] =?UTF-8?q?[Console]=C2=A0Fix=20infinite=20loop=20on=20mis?= =?UTF-8?q?sing=20input?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Console] Use console exception for missing input Backport Console RuntimeException in 2.7 --- .../Console/Exception/RuntimeException.php | 19 ++++++++++++ .../Console/Helper/QuestionHelper.php | 9 ++++-- .../Tests/Helper/QuestionHelperTest.php | 31 +++++++++++++++++++ .../Helper/SymfonyQuestionHelperTest.php | 12 +++++++ 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Console/Exception/RuntimeException.php diff --git a/src/Symfony/Component/Console/Exception/RuntimeException.php b/src/Symfony/Component/Console/Exception/RuntimeException.php new file mode 100644 index 0000000000..1324558a7b --- /dev/null +++ b/src/Symfony/Component/Console/Exception/RuntimeException.php @@ -0,0 +1,19 @@ + + * + * 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 + */ +class RuntimeException extends \RuntimeException +{ +} diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 6d6850d1ae..90055b8a70 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -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) { } } diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index 6a4f8aceae..86ad446c1b 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -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); diff --git a/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php index 91f51245ac..f57d65070e 100644 --- a/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php @@ -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);