From be056fd0bf1a15a87a73f33fba8a9d5d645a427c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Par=C3=A1da=20J=C3=B3zsef?= Date: Sun, 17 Jan 2016 01:29:59 +0100 Subject: [PATCH] [Form] ChoiceType: Fix a notice when 'choices' normalizer is replaced --- .../Form/Extension/Core/Type/ChoiceType.php | 4 ++ .../Extension/Core/Type/ChoiceTypeTest.php | 27 ++++++++++ .../Form/Tests/Fixtures/ChoiceSubType.php | 51 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/ChoiceSubType.php diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index ef9a4b5bae..515f104af6 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -291,6 +291,10 @@ class ChoiceType extends AbstractType // forms) $labels = $choiceLabels->labels; + // The $choiceLabels object is shared with the 'choices' closure. + // Since that normalizer can be replaced, labels have to be cleared here. + $choiceLabels->labels = array(); + return function ($choice, $key) use ($labels) { return $labels[$key]; }; diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index d7536f7640..cf74fec212 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; +use Symfony\Component\Form\Tests\Fixtures\ChoiceSubType; class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { @@ -1887,4 +1888,30 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase // Trigger data initialization $form->getViewData(); } + + /** + * This covers the case when: + * - Custom choice type added after a choice type. + * - Custom type is expanded. + * - Custom type replaces 'choices' normalizer with a custom one. + * In this case, custom type should not inherit labels from the first added choice type. + */ + public function testCustomChoiceTypeDoesNotInheritChoiceLabels() + { + $builder = $this->factory->createBuilder(); + $builder->add('choice', 'choice', array( + 'choices' => array( + '1' => '1', + '2' => '2', + ), + ) + ); + $builder->add('subChoice', new ChoiceSubType()); + $form = $builder->getForm(); + + // The default 'choices' normalizer would fill the $choiceLabels, but it has been replaced + // in the custom choice type, so $choiceLabels->labels remains empty array. + // In this case the 'choice_label' closure returns null and not the closure from the first choice type. + $this->assertNull($form->get('subChoice')->getConfig()->getOption('choice_label')); + } } diff --git a/src/Symfony/Component/Form/Tests/Fixtures/ChoiceSubType.php b/src/Symfony/Component/Form/Tests/Fixtures/ChoiceSubType.php new file mode 100644 index 0000000000..857dd5d5a7 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/ChoiceSubType.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * @author Paráda József + */ +class ChoiceSubType extends AbstractType +{ + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults(array('expanded' => true)); + $resolver->setNormalizer('choices', function () { + return array( + 'attr1' => 'Attribute 1', + 'attr2' => 'Attribute 2', + ); + }); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'sub_choice'; + } + + /** + * {@inheritdoc} + */ + public function getParent() + { + return 'choice'; + } +}