diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 67decd30beae3..cda9e1a9efc92 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.4.0 +----- + +* added `Question::setTrimmable` default to true to allow the answer to be trimmed or not + 4.3.0 ----- diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index e6a700aa45db0..a20d141433ed0 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -64,7 +64,7 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu $default = explode(',', $default); foreach ($default as $k => $v) { - $v = trim($v); + $v = $question->isTrimmable() ? trim($v) : $v; $default[$k] = isset($choices[$v]) ? $choices[$v] : $v; } } @@ -121,7 +121,8 @@ private function doAsk(OutputInterface $output, Question $question) $ret = false; if ($question->isHidden()) { try { - $ret = trim($this->getHiddenResponse($output, $inputStream)); + $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable()); + $ret = $question->isTrimmable() ? trim($hiddenResponse) : $hiddenResponse; } catch (RuntimeException $e) { if (!$question->isHiddenFallback()) { throw $e; @@ -134,10 +135,13 @@ private function doAsk(OutputInterface $output, Question $question) if (false === $ret) { throw new RuntimeException('Aborted.'); } - $ret = trim($ret); + if ($question->isTrimmable()) { + $ret = trim($ret); + } } } else { - $ret = trim($this->autocomplete($output, $question, $inputStream, $autocomplete)); + $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete); + $ret = $question->isTrimmable() ? trim($autocomplete) : $autocomplete; } if ($output instanceof ConsoleSectionOutput) { @@ -351,10 +355,11 @@ private function mostRecentlyEnteredValue($entered) * * @param OutputInterface $output An Output instance * @param resource $inputStream The handler resource + * @param bool $trimmable Is the answer trimmable * * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ - private function getHiddenResponse(OutputInterface $output, $inputStream): string + private function getHiddenResponse(OutputInterface $output, $inputStream, $trimmable = true): string { if ('\\' === \DIRECTORY_SEPARATOR) { $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; @@ -366,7 +371,8 @@ private function getHiddenResponse(OutputInterface $output, $inputStream): strin $exe = $tmpExe; } - $value = rtrim(shell_exec($exe)); + $sExec = shell_exec($exe); + $value = $trimmable ? rtrim($sExec) : $sExec; $output->writeln(''); if (isset($tmpExe)) { @@ -386,8 +392,9 @@ private function getHiddenResponse(OutputInterface $output, $inputStream): strin if (false === $value) { throw new RuntimeException('Aborted.'); } - - $value = trim($value); + if ($trimmable) { + $value = trim($value); + } $output->writeln(''); return $value; @@ -396,7 +403,8 @@ private function getHiddenResponse(OutputInterface $output, $inputStream): strin if (false !== $shell = $this->getShell()) { $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword'; $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); - $value = rtrim(shell_exec($command)); + $sCommand = shell_exec($command); + $value = $trimmable ? rtrim($sCommand) : $sCommand; $output->writeln(''); return $value; diff --git a/src/Symfony/Component/Console/Question/Question.php b/src/Symfony/Component/Console/Question/Question.php index 9201af2fd5d82..43ad8b0917cd0 100644 --- a/src/Symfony/Component/Console/Question/Question.php +++ b/src/Symfony/Component/Console/Question/Question.php @@ -29,6 +29,7 @@ class Question private $validator; private $default; private $normalizer; + private $trimmable = true; /** * @param string $question The question to ask to the user @@ -274,4 +275,19 @@ protected function isAssoc($array) { return (bool) \count(array_filter(array_keys($array), 'is_string')); } + + public function isTrimmable(): bool + { + return $this->trimmable; + } + + /** + * @return $this + */ + public function setTrimmable(bool $trimmable): self + { + $this->trimmable = $trimmable; + + return $this; + } } diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index eca929fd306b4..19e9f355d41bd 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -165,6 +165,20 @@ public function testAsk() $this->assertEquals('What time is it?', stream_get_contents($output->getStream())); } + public function testAskNonTrimmed() + { + $dialog = new QuestionHelper(); + + $inputStream = $this->getInputStream(' 8AM '); + + $question = new Question('What time is it?', '2PM'); + $question->setTrimmable(false); + $this->assertEquals(' 8AM ', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $output = $this->createOutputInterface(), $question)); + + rewind($output->getStream()); + $this->assertEquals('What time is it?', stream_get_contents($output->getStream())); + } + public function testAskWithAutocomplete() { if (!$this->hasSttyAvailable()) { @@ -198,6 +212,40 @@ public function testAskWithAutocomplete() $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); } + public function testAskWithAutocompleteTrimmable() + { + if (!$this->hasSttyAvailable()) { + $this->markTestSkipped('`stty` is required to test autocomplete functionality'); + } + + // Acm + // AcsTest + // + // + // Test + // + // S + // F00oo + $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"); + + $dialog = new QuestionHelper(); + $helperSet = new HelperSet([new FormatterHelper()]); + $dialog->setHelperSet($helperSet); + + $question = new Question('Please select a bundle', 'FrameworkBundle'); + $question->setAutocompleterValues(['AcmeDemoBundle ', 'AsseticBundle', ' SecurityBundle ', 'FooBundle']); + $question->setTrimmable(false); + + $this->assertEquals('AcmeDemoBundle ', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('FrameworkBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals(' SecurityBundle ', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundleTest', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AcmeDemoBundle ', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('AsseticBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + $this->assertEquals('FooBundle', $dialog->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + } + public function testAskWithAutocompleteCallback() { if (!$this->hasSttyAvailable()) { @@ -373,6 +421,21 @@ public function testAskHiddenResponse() $this->assertEquals('8AM', $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("8AM\n")), $this->createOutputInterface(), $question)); } + public function testAskHiddenResponseTrimmed() + { + if ('\\' === \DIRECTORY_SEPARATOR) { + $this->markTestSkipped('This test is not supported on Windows'); + } + + $dialog = new QuestionHelper(); + + $question = new Question('What time is it?'); + $question->setHidden(true); + $question->setTrimmable(false); + + $this->assertEquals(' 8AM', $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream(' 8AM')), $this->createOutputInterface(), $question)); + } + /** * @dataProvider getAskConfirmationData */ pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy