bug #17314 Fix max width for multibyte keys in choice question (mheki)

This PR was submitted for the 2.8 branch but it was merged into the 2.7 branch instead (closes #17314).

Discussion
----------

Fix max width for multibyte keys in choice question

Fixes wrong key max width for ChoiceQuestion in multibyte strings

Before:
![before](https://cloud.githubusercontent.com/assets/2435655/12203385/977e88c0-b626-11e5-9425-d497f84a9ab3.png)

After:
![after](https://cloud.githubusercontent.com/assets/2435655/12203390/9d9a0b4e-b626-11e5-8d4e-ba9290820778.png)

To replicate you can use this code as an example:
```
namespace AppBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ChoiceQuestion;

class QuesionCommand extends Command
{
    protected function configure()
    {
        $this->setName('app:question');
        $this->setDescription('Command for testing PR');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $helper = $this->getHelper('question');

        $question = new ChoiceQuestion('Choose something:',
            [
                'foo' => 'foo',
                'żółw' => 'bar',
                'łabądź' => 'baz',
                'известно' => 'lorem',
                'газета' => 'ipsum',
            ],
            0);

        $colour = $helper->ask($input, $output, $question);
        $output->writeln('you have chosen: ' . $colour);
    }
}
```

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | https://github.com/symfony/symfony/issues/15368
| License       | MIT
| Doc PR        | -

Commits
-------

5d2463b Fix max width for multibyte keys in choice question
This commit is contained in:
Fabien Potencier 2016-01-14 09:06:08 +01:00
commit 6a870f12ae
2 changed files with 32 additions and 2 deletions

View File

@ -162,11 +162,12 @@ class QuestionHelper extends Helper
$message = $question->getQuestion();
if ($question instanceof ChoiceQuestion) {
$width = max(array_map('strlen', array_keys($question->getChoices())));
$maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
$messages = (array) $question->getQuestion();
foreach ($question->getChoices() as $key => $value) {
$messages[] = sprintf(" [<info>%-${width}s</info>] %s", $key, $value);
$width = $maxWidth - $this->strlen($key);
$messages[] = ' [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
}
$output->writeln($messages);

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Console\Tests\Helper;
use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
@ -350,6 +351,34 @@ class QuestionHelperTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('not yet', $dialog->ask($this->createInputInterfaceMock(false), $this->createOutputInterface(), $question));
}
public function testChoiceOutputFormattingQuestionForUtf8Keys()
{
$question = 'Lorem ipsum?';
$possibleChoices = array(
'foo' => 'foo',
'żółw' => 'bar',
'łabądź' => 'baz',
);
$outputShown = array(
$question,
' [<info>foo </info>] foo',
' [<info>żółw </info>] bar',
' [<info>łabądź</info>] baz',
);
$output = $this->getMock('\Symfony\Component\Console\Output\OutputInterface');
$output->method('getFormatter')->willReturn(new OutputFormatter());
$dialog = new QuestionHelper();
$dialog->setInputStream($this->getInputStream("\n"));
$helperSet = new HelperSet(array(new FormatterHelper()));
$dialog->setHelperSet($helperSet);
$output->expects($this->once())->method('writeln')->with($this->equalTo($outputShown));
$question = new ChoiceQuestion($question, $possibleChoices, 'foo');
$dialog->ask($this->createInputInterfaceMock(), $output, $question);
}
protected function getInputStream($input)
{
$stream = fopen('php://memory', 'r+', false);