bug #17798 [Form] allow choice_label
option to be false
When `ChoiceType`is expanded, `choice_label` option can be `false` or return `false` for one or more choices by a callable.
This commit is contained in:
parent
22383987e0
commit
017e1d9e6e
@ -155,11 +155,21 @@ class DefaultChoiceListFactory implements ChoiceListFactoryInterface
|
|||||||
$key = $keys[$value];
|
$key = $keys[$value];
|
||||||
$nextIndex = is_int($index) ? $index++ : call_user_func($index, $choice, $key, $value);
|
$nextIndex = is_int($index) ? $index++ : call_user_func($index, $choice, $key, $value);
|
||||||
|
|
||||||
|
// BC normalize label to accept a false value
|
||||||
|
if (null === $label) {
|
||||||
|
// If the labels are null, use the original choice key by default
|
||||||
|
$label = (string) $key;
|
||||||
|
} elseif (false !== $label) {
|
||||||
|
// If "choice_label" is set to false and "expanded" is true, the value false
|
||||||
|
// should be passed on to the "label" option of the checkboxes/radio buttons
|
||||||
|
$dynamicLabel = call_user_func($label, $choice, $key, $value);
|
||||||
|
$label = false === $dynamicLabel ? false : (string) $dynamicLabel;
|
||||||
|
}
|
||||||
|
|
||||||
$view = new ChoiceView(
|
$view = new ChoiceView(
|
||||||
$choice,
|
$choice,
|
||||||
$value,
|
$value,
|
||||||
// If the labels are null, use the original choice key by default
|
$label,
|
||||||
null === $label ? (string) $key : (string) call_user_func($label, $choice, $key, $value),
|
|
||||||
// The attributes may be a callable or a mapping from choice indices
|
// The attributes may be a callable or a mapping from choice indices
|
||||||
// to nested arrays
|
// to nested arrays
|
||||||
is_callable($attr) ? call_user_func($attr, $choice, $key, $value) : (isset($attr[$key]) ? $attr[$key] : array())
|
is_callable($attr) ? call_user_func($attr, $choice, $key, $value) : (isset($attr[$key]) ? $attr[$key] : array())
|
||||||
|
@ -413,7 +413,7 @@ class ChoiceType extends AbstractType
|
|||||||
$resolver->setAllowedTypes('choice_translation_domain', array('null', 'bool', 'string'));
|
$resolver->setAllowedTypes('choice_translation_domain', array('null', 'bool', 'string'));
|
||||||
$resolver->setAllowedTypes('choices_as_values', 'bool');
|
$resolver->setAllowedTypes('choices_as_values', 'bool');
|
||||||
$resolver->setAllowedTypes('choice_loader', array('null', 'Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface'));
|
$resolver->setAllowedTypes('choice_loader', array('null', 'Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface'));
|
||||||
$resolver->setAllowedTypes('choice_label', array('null', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath'));
|
$resolver->setAllowedTypes('choice_label', array('null', 'bool', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath'));
|
||||||
$resolver->setAllowedTypes('choice_name', array('null', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath'));
|
$resolver->setAllowedTypes('choice_name', array('null', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath'));
|
||||||
$resolver->setAllowedTypes('choice_value', array('null', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath'));
|
$resolver->setAllowedTypes('choice_value', array('null', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath'));
|
||||||
$resolver->setAllowedTypes('choice_attr', array('null', 'array', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath'));
|
$resolver->setAllowedTypes('choice_attr', array('null', 'array', 'callable', 'string', 'Symfony\Component\PropertyAccess\PropertyPath'));
|
||||||
|
@ -690,6 +690,129 @@ abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSingleChoiceExpandedWithLabelsAsFalse()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', '&a', array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => false,
|
||||||
|
'multiple' => false,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./div
|
||||||
|
[@class="radio"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::div
|
||||||
|
[@class="radio"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleChoiceExpandedWithLabelsSetByCallable()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', '&a', array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => function ($choice, $label, $value) {
|
||||||
|
if ('&b' === $choice) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'label.'.$value;
|
||||||
|
},
|
||||||
|
'multiple' => false,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./div
|
||||||
|
[@class="radio"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[.=" [trans]label.&a[/trans]"]
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::div
|
||||||
|
[@class="radio"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::div
|
||||||
|
[@class="radio"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[.=" [trans]label.&c[/trans]"]
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_2"][@value="&c"][not(@checked)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleChoiceExpandedWithLabelsSetFalseByCallable()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', '&a', array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
'multiple' => false,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./div
|
||||||
|
[@class="radio"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::div
|
||||||
|
[@class="radio"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSingleChoiceExpandedWithoutTranslation()
|
public function testSingleChoiceExpandedWithoutTranslation()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('name', 'choice', '&a', array(
|
$form = $this->factory->createNamed('name', 'choice', '&a', array(
|
||||||
@ -895,6 +1018,129 @@ abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testMultipleChoiceExpandedWithLabelsAsFalse()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', array('&a'), array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => false,
|
||||||
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./div
|
||||||
|
[@class="checkbox"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::div
|
||||||
|
[@class="checkbox"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultipleChoiceExpandedWithLabelsSetByCallable()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', array('&a'), array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => function ($choice, $label, $value) {
|
||||||
|
if ('&b' === $choice) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'label.'.$value;
|
||||||
|
},
|
||||||
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./div
|
||||||
|
[@class="checkbox"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[.=" [trans]label.&a[/trans]"]
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::div
|
||||||
|
[@class="checkbox"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::div
|
||||||
|
[@class="checkbox"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[.=" [trans]label.&c[/trans]"]
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_2"][@value="&c"][not(@checked)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', array('&a'), array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./div
|
||||||
|
[@class="checkbox"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::div
|
||||||
|
[@class="checkbox"]
|
||||||
|
[
|
||||||
|
./label
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"]
|
||||||
|
]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testMultipleChoiceExpandedWithoutTranslation()
|
public function testMultipleChoiceExpandedWithoutTranslation()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('name', 'choice', array('&a', '&c'), array(
|
$form = $this->factory->createNamed('name', 'choice', array('&a', '&c'), array(
|
||||||
|
@ -708,6 +708,166 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSingleChoiceExpandedWithLabelsAsFalse()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', '&a', array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => false,
|
||||||
|
'multiple' => false,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"]
|
||||||
|
]
|
||||||
|
[count(./input)=3]
|
||||||
|
[count(./label)=1]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleChoiceExpandedWithLabelsSetByCallable()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', '&a', array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => function ($choice, $label, $value) {
|
||||||
|
if ('&b' === $choice) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'label.'.$value;
|
||||||
|
},
|
||||||
|
'multiple' => false,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
/following-sibling::label[@for="name_0"][.="[trans]label.&a[/trans]"]
|
||||||
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_2"][@value="&c"][not(@checked)]
|
||||||
|
/following-sibling::label[@for="name_2"][.="[trans]label.&c[/trans]"]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"]
|
||||||
|
]
|
||||||
|
[count(./input)=4]
|
||||||
|
[count(./label)=3]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSingleChoiceExpandedWithLabelsSetFalseByCallable()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', '&a', array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
'multiple' => false,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"]
|
||||||
|
]
|
||||||
|
[count(./input)=3]
|
||||||
|
[count(./label)=1]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultipleChoiceExpandedWithLabelsAsFalse()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', array('&a'), array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => false,
|
||||||
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"]
|
||||||
|
]
|
||||||
|
[count(./input)=3]
|
||||||
|
[count(./label)=1]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultipleChoiceExpandedWithLabelsSetByCallable()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', array('&a'), array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => function ($choice, $label, $value) {
|
||||||
|
if ('&b' === $choice) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'label.'.$value;
|
||||||
|
},
|
||||||
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
/following-sibling::label[@for="name_0"][.="[trans]label.&a[/trans]"]
|
||||||
|
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_2"][@value="&c"][not(@checked)]
|
||||||
|
/following-sibling::label[@for="name_2"][.="[trans]label.&c[/trans]"]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"]
|
||||||
|
]
|
||||||
|
[count(./input)=4]
|
||||||
|
[count(./label)=3]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'choice', array('&a'), array(
|
||||||
|
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
|
||||||
|
'choices_as_values' => true,
|
||||||
|
'choice_label' => function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
'multiple' => true,
|
||||||
|
'expanded' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||||
|
'/div
|
||||||
|
[
|
||||||
|
./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked]
|
||||||
|
/following-sibling::input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)]
|
||||||
|
/following-sibling::input[@type="hidden"][@id="name__token"]
|
||||||
|
]
|
||||||
|
[count(./input)=3]
|
||||||
|
[count(./label)=1]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testFormEndWithRest()
|
public function testFormEndWithRest()
|
||||||
{
|
{
|
||||||
$view = $this->factory->createNamedBuilder('name', 'form')
|
$view = $this->factory->createNamedBuilder('name', 'form')
|
||||||
|
Reference in New Issue
Block a user