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 | https://github.com/symfony/symfony/issues/31572
| License | MIT
| Doc PR | -
This is the 3.4 version of https://github.com/symfony/symfony/pull/32747. The tests are the same. The added code has to be removed from master (if accepted).
Commits
-------
1a366bc378
[Form] Handle false as empty value on expanded choices
This commit is contained in:
commit
aaddef3c57
|
@ -33,6 +33,7 @@ class CheckboxType extends AbstractType
|
||||||
// doing so also calls setDataLocked(true).
|
// doing so also calls setDataLocked(true).
|
||||||
$builder->setData(isset($options['data']) ? $options['data'] : false);
|
$builder->setData(isset($options['data']) ? $options['data'] : false);
|
||||||
$builder->addViewTransformer(new BooleanToStringTransformer($options['value']));
|
$builder->addViewTransformer(new BooleanToStringTransformer($options['value']));
|
||||||
|
$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.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -725,7 +725,9 @@ class Form implements \IteratorAggregate, FormInterface
|
||||||
// arrays, countables
|
// arrays, countables
|
||||||
((\is_array($this->modelData) || $this->modelData instanceof \Countable) && 0 === \count($this->modelData)) ||
|
((\is_array($this->modelData) || $this->modelData instanceof \Countable) && 0 === \count($this->modelData)) ||
|
||||||
// traversables that are not countable
|
// traversables that are not countable
|
||||||
($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData));
|
($this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData)) ||
|
||||||
|
// @internal - Do not rely on it, it will be removed in Symfony 5.1.
|
||||||
|
(false === $this->modelData && $this->config->getAttribute('_false_is_empty'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -190,4 +190,13 @@ class CheckboxTypeTest extends BaseTypeTest
|
||||||
$this->assertSame($expectedData, $form->getNormData());
|
$this->assertSame($expectedData, $form->getNormData());
|
||||||
$this->assertSame($expectedData, $form->getData());
|
$this->assertSame($expectedData, $form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSubmitNullIsEmpty()
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE);
|
||||||
|
|
||||||
|
$form->submit(null);
|
||||||
|
|
||||||
|
$this->assertTrue($form->isEmpty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2046,4 +2046,45 @@ class ChoiceTypeTest extends BaseTypeTest
|
||||||
'Multiple expanded' => [true, true],
|
'Multiple expanded' => [true, true],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider expandedIsEmptyWhenNoRealChoiceIsSelectedProvider
|
||||||
|
*/
|
||||||
|
public function testExpandedIsEmptyWhenNoRealChoiceIsSelected($expected, $submittedData, $multiple, $required, $placeholder)
|
||||||
|
{
|
||||||
|
$options = [
|
||||||
|
'expanded' => true,
|
||||||
|
'choices' => [
|
||||||
|
'foo' => 'bar',
|
||||||
|
],
|
||||||
|
'multiple' => $multiple,
|
||||||
|
'required' => $required,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!$multiple) {
|
||||||
|
$options['placeholder'] = $placeholder;
|
||||||
|
}
|
||||||
|
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, $options);
|
||||||
|
|
||||||
|
$form->submit($submittedData);
|
||||||
|
|
||||||
|
$this->assertSame($expected, $form->isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function expandedIsEmptyWhenNoRealChoiceIsSelectedProvider()
|
||||||
|
{
|
||||||
|
// Some invalid cases are voluntarily not tested:
|
||||||
|
// - multiple with placeholder
|
||||||
|
// - required with placeholder
|
||||||
|
return [
|
||||||
|
'Nothing submitted / single / not required / without a placeholder -> should be empty' => [true, null, false, false, null],
|
||||||
|
'Nothing submitted / single / not required / with a placeholder -> should not be empty' => [false, null, false, false, 'ccc'], // It falls back on the placeholder
|
||||||
|
'Nothing submitted / single / required / without a placeholder -> should be empty' => [true, null, false, true, null],
|
||||||
|
'Nothing submitted / single / required / with a placeholder -> should be empty' => [true, null, false, true, 'ccc'],
|
||||||
|
'Nothing submitted / multiple / not required / without a placeholder -> should be empty' => [true, null, true, false, null],
|
||||||
|
'Nothing submitted / multiple / required / without a placeholder -> should be empty' => [true, null, true, true, null],
|
||||||
|
'Placeholder submitted / single / not required / with a placeholder -> should not be empty' => [false, '', false, false, 'ccc'], // The placeholder is a selected value
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue