8000 bug #17406 [Form] ChoiceType: Fix a notice when 'choices' normalizer … · symfony/symfony@414ddf7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 414ddf7

Browse files
committed
bug #17406 [Form] ChoiceType: Fix a notice when 'choices' normalizer is replaced (paradajozsef)
This PR was squashed before being merged into the 2.7 branch (closes #17406). Discussion ---------- [Form] ChoiceType: Fix a notice when 'choices' normalizer is replaced | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #17270 | License | MIT | Doc PR | - As @gseidel [mentioned](#17270 (comment)), the notice only occurs, when a custom choice field added after a choice field **and** the custom type is expanded, **and** the ```'choices'``` normalizer is replaced. The problem is that when ```'choices'``` option is replaced, the [default choiceNormalizer](https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php#L262) is not invoked. This normalizer would [clear](https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php#L264) the labels from previous invocation, but it's been replaced in the custom choice type. As a result [$choiceLabel](https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php#L279) normalizer will get the wrong labels because it shares the same scope with [$choiceNormalizer](https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php#L262). Resetting the label values after copy solves this problem. Commits ------- be056fd [Form] ChoiceType: Fix a notice when 'choices' normalizer is replaced
2 parents d55f73f + be056fd commit 414ddf7

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ public function configureOptions(OptionsResolver $resolver)
291291
// forms)
292292
$labels = $choiceLabels->labels;
293293

294+
// The $choiceLabels object is shared with the 'choices' closure.
295+
// Since that normalizer can be replaced, labels have to be cleared here.
296+
$choiceLabels->labels = array();
297+
294298
return function ($choice, $key) use ($labels) {
295299
return $labels[$key];
296300
};

src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView;
1515
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
1616
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
17+
use Symfony\Component\Form\Tests\Fixtures\ChoiceSubType;
1718

1819
class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
1920
{
@@ -1887,4 +1888,30 @@ public function testInitializeWithDefaultObjectChoice()
18871888
// Trigger data initialization
18881889
$form->getViewData();
18891890
}
1891+
1892+
/**
1893+
* This covers the case when:
1894+
* - Custom choice type added after a choice type.
1895+
* - Custom type is expanded.
1896+
* - Custom type replaces 'choices' normalizer with a custom one.
1897+
* In this case, custom type should not inherit labels from the first added choice type.
1898+
*/
1899+
public function testCustomChoiceTypeDoesNotInheritChoiceLabels()
1900+
{
1901+
$builder = $this->factory->createBuilder();
1902+
$builder->add('choice', 'choice', array(
1903+
'choices' => array(
1904+
'1' => '1',
1905+
'2' => '2',
1906+
),
1907+
)
1908+
);
1909+
$builder->add('subChoice', new ChoiceSubType());
1910+
$form = $builder->getForm();
1911+
1912+
// The default 'choices' normalizer would fill the $choiceLabels, but it has been replaced
1913+
// in the custom choice type, so $choiceLabels->labels remains empty array.
1914+
// In this case the 'choice_label' closure returns null and not the closure from the first choice type.
1915+
$this->assertNull($form->get('subChoice')->getConfig()->getOption('choice_label'));
1916+
}
18901917
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Tests\Fixtures;
13+
14+
use Symfony\Component\Form\AbstractType;
15+
use Symfony\Component\OptionsResolver\OptionsResolver;
16+
17+
/**
18+
* @author Paráda József <joczy.parada@gmail.com>
19+
*/
20+
class ChoiceSubType extends AbstractType
21+
{
22+
/**
23+
* {@inheritdoc}
24+
*/
25+
public function configureOptions(OptionsResolver $resolver)
26+
{
27+
$resolver->setDefaults(array('expanded' => true));
28+
$resolver->setNormalizer('choices', function () {
29+
return array(
30+
A64F 'attr1' => 'Attribute 1',
31+
'attr2' => 'Attribute 2',
32+
);
33+
});
34+
}
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function getName()
40+
{
41+
return 'sub_choice';
42+
}
43+
44+
/**
45+
* {@inheritdoc}
46+
*/
47+
public function getParent()
48+
{
49+
return 'choice';
50+
}
51+
}

0 commit comments

Comments
 (0)
0