8000 bug #35938 [Form] Handle false as empty value on expanded choices (fa… · symfony/symfony@aaddef3 · GitHub
[go: up one dir, main page]

Skip to content

Commit aaddef3

Browse files
bug #35938 [Form] Handle false as empty value on expanded choices (fancyweb)
This PR was merged into the 3.4 branch. Discussion ---------- [Form] Handle false as empty value on expanded choices | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | #31572 | License | MIT | Doc PR | - This is the 3.4 version of #32747. The tests are the same. The added code has to be removed from master (if accepted). Commits ------- 1a366bc [Form] Handle false as empty value on expanded choices
2 parents cd08bf4 + 1a366bc commit aaddef3

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
3333
// doing so also calls setDataLocked(true).
3434
$builder->setData(isset($options['data']) ? $options['data'] : false);
3535
$builder->addViewTransformer(new BooleanToStringTransformer($options['value']));
36+
$builder->setAttribute('_false_is_empty', true); // @internal - A boolean flag to treat false as empty, see Form::isEmpty() - Do not rely on it, it will be removed in Symfony 5.1.
3637
}
3738

3839
/**

src/Symfony/Component/Form/Form.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,9 @@ public function isEmpty()
725725
// arrays, countables
726726
((\is_array($this->modelData) || $this->modelData instanceof \Countable) && 0 === \count($this->modelData)) ||
727727
// traversables that are not countable
728-
($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData));
728+
($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData)) ||
729+
// @internal - Do not rely on it, it will be removed in Symfony 5.1.
730+
(false === $this->modelData && $this->config->getAttribute('_false_is_empty'));
729731
}
730732

731733
/**

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,13 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = 'empty', $expect
190190
$this->assertSame($expectedData, $form->getNormData());
191191
$this->assertSame($expectedData, $form->getData());
192192
}
193+
194+
public function testSubmitNullIsEmpty()
195+
{
196+
$form = $this->factory->create(static::TESTED_TYPE);
197+
198+
$form->submit(null);
199+
200+
$this->assertTrue($form->isEmpty());
201+
}
193202
}

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,4 +2046,45 @@ public function provideTrimCases()
20462046
'Multiple expanded' => [true, true],
20472047
];
20482048
}
2049+
2050+
/**
2051+
* @dataProvider expandedIsEmptyWhenNoRealChoiceIsSelectedProvider
2052+
*/
2053+
public function testExpandedIsEmptyWhenNoRealChoiceIsSelected($expected, $submittedData, $multiple, $required, $placeholder)
2054+
{
2055+
$options = [
2056+
'expanded' => true,
2057+
'choices' => [
2058+
'foo' => 'bar',
2059+
],
2060+
'multiple' => $multiple,
2061+
'required' => $required,
2062+
];
2063+
2064+
if (!$multiple) {
2065+
$options['placeholder'] = $placeholder;
2066+
}
2067+
2068+
$form = $this->factory->create(static::TESTED_TYPE, null, $options);
2069+
2070+
$form->submit($submittedData);
2071+
2072+
$this->assertSame($expected, $form->isEmpty());
2073+
}
2074+
2075+
public function expandedIsEmptyWhenNoRealChoiceIsSelectedProvider()
2076+
{
2077+
// Some invalid cases are voluntarily not tested:
2078+
// - multiple with placeholder
2079+
// - required with placeholder
2080+
return [
2081+
'Nothing submitted / single / not required / without a placeholder -> should be empty' => [true, null, false, false, null],
2082+
'Nothing submitted / single / not required / with a placeholder -> should not be empty' => [false, null, false, false, 'ccc'], // It falls back on the placeholder
2083+
'Nothing submitted / single / required / without a placeholder -> should be empty' => [true, null, false, true, null],
2084+
'Nothing submitted / single / required / with a placeholder -> should be empty' => [true, null, false, true, 'ccc'],
2085+
'Nothing submitted / multiple / not required / without a placeholder -> should be empty' => [true, null, true, false, null],
2086+
'Nothing submitted / multiple / required / without a placeholder -> should be empty' => [true, null, true, true, null],
2087+
'Placeholder submitted / single / not required / with a placeholder -> should not be empty' => [false, '', false, false, 'ccc'], // The placeholder is a selected value
2088+
];
2089+
}
20492090
}

0 commit comments

Comments
 (0)
0