Skip to content

Commit d2d373e

Browse files
committed
bug #25741 [Form] issue-13589: adding custom false-values to BooleanToString transformer (leberknecht)
This PR was squashed before being merged into the 4.1-dev branch (closes #25741). Discussion ---------- [Form] issue-13589: adding custom false-values to BooleanToString transformer | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #13589 | License | MIT | Doc PR | symfony/symfony-docs#9031 As suggested in #13589 , this PR adds the option to specify custom false-values, so we can use the CheckBoxType to handle strings '1' / '0' and eval them to true / false. While HTTP defines that checkbox types are either submitted=true or not-submitted=false, no matter of what value was submitted, it would be nice to have this option. Also refs (which read like "the basic idea of the feature was accepted, PR almost done, then something-happend so PR wasnt merged"..?) symfony/symfony#15054 symfony/symfony#18005 Commits ------- a3e5ac496f [Form] issue-13589: adding custom false-values to BooleanToString transformer
2 parents d573591 + 9ce0092 commit d2d373e

File tree

5 files changed

+70
-4
lines changed

5 files changed

+70
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ CHANGELOG
1919
* removed passing guesser services ids as the fourth argument of `DependencyInjectionExtension::__construct()`
2020
* removed the ability to validate an unsubmitted form.
2121
* removed `ChoiceLoaderInterface` implementation in `TimezoneType`
22+
* added the `false_values` option to the `CheckboxType` which allows to configure custom values which will be treated as `false` during submission
2223

2324
3.4.0
2425
-----

Extension/Core/DataTransformer/BooleanToStringTransformer.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Form\Extension\Core\DataTransformer;
1313

1414
use Symfony\Component\Form\DataTransformerInterface;
15+
use Symfony\Component\Form\Exception\InvalidArgumentException;
1516
use Symfony\Component\Form\Exception\TransformationFailedException;
1617

1718
/**
@@ -24,12 +25,19 @@ class BooleanToStringTransformer implements DataTransformerInterface
2425
{
2526
private $trueValue;
2627

28+
private $falseValues;
29+
2730
/**
28-
* @param string $trueValue The value emitted upon transform if the input is true
31+
* @param string $trueValue The value emitted upon transform if the input is true
32+
* @param array $falseValues
2933
*/
30-
public function __construct(string $trueValue)
34+
public function __construct(string $trueValue, array $falseValues = array(null))
3135
{
3236
$this->trueValue = $trueValue;
37+
$this->falseValues = $falseValues;
38+
if (in_array($this->trueValue, $this->falseValues, true)) {
39+
throw new InvalidArgumentException('The specified "true" value is contained in the false-values');
40+
}
3341
}
3442

3543
/**
@@ -65,7 +73,7 @@ public function transform($value)
6573
*/
6674
public function reverseTransform($value)
6775
{
68-
if (null === $value) {
76+
if (in_array($value, $this->falseValues, true)) {
6977
return false;
7078
}
7179

Extension/Core/Type/CheckboxType.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
3232
// We cannot solve this case via overriding the "data" option, because
3333
// doing so also calls setDataLocked(true).
3434
$builder->setData(isset($options['data']) ? $options['data'] : false);
35-
$builder->addViewTransformer(new BooleanToStringTransformer($options['value']));
35+
$builder->addViewTransformer(new BooleanToStringTransformer($options['value'], $options['false_values']));
3636
}
3737

3838
/**
@@ -59,7 +59,10 @@ public function configureOptions(OptionsResolver $resolver)
5959
'value' => '1',
6060
'empty_data' => $emptyData,
6161
'compound' => false,
62+
'false_values' => array(null),
6263
));
64+
65+
$resolver->setAllowedTypes('false_values', 'array');
6366
}
6467

6568
/**

Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,26 @@ public function testReverseTransform()
6868
$this->assertTrue($this->transformer->reverseTransform(''));
6969
$this->assertFalse($this->transformer->reverseTransform(null));
7070
}
71+
72+
public function testCustomFalseValues()
73+
{
74+
$customFalseTransformer = new BooleanToStringTransformer(self::TRUE_VALUE, array('0', 'myFalse', true));
75+
$this->assertFalse($customFalseTransformer->reverseTransform('myFalse'));
76+
$this->assertFalse($customFalseTransformer->reverseTransform('0'));
77+
$this->assertFalse($customFalseTransformer->reverseTransform(true));
78+
}
79+
80+
/**
81+
* @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException
82+
*/
83+
public function testTrueValueContainedInFalseValues()
84+
{
85+
new BooleanToStringTransformer('0', array(null, '0'));
86+
}
87+
88+
public function testBeStrictOnTrueInFalseValueCheck()
89+
{
90+
$transformer = new BooleanToStringTransformer('0', array(null, false));
91+
$this->assertInstanceOf(BooleanToStringTransformer::class, $transformer);
92+
}
7193
}

Tests/Extension/Core/Type/CheckboxTypeTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,38 @@ public function provideCustomModelTransformerData()
173173
);
174174
}
175175

176+
/**
177+
* @dataProvider provideCustomFalseValues
178+
*/
179+
public function testCustomFalseValues($falseValue)
180+
{
181+
$form = $this->factory->create(static::TESTED_TYPE, null, array(
182+
'false_values' => array($falseValue),
183+
));
184+
$form->submit($falseValue);
185+
$this->assertFalse($form->getData());
186+
}
187+
188+
public function provideCustomFalseValues()
189+
{
190+
return array(
191+
array(''),
192+
array('false'),
193+
array('0'),
194+
);
195+
}
196+
197+
/**
198+
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
199+
*/
200+
public function testDontAllowNonArrayFalseValues()
201+
{
202+
$this->expectExceptionMessageRegExp('/"false_values" with value "invalid" is expected to be of type "array"/');
203+
$this->factory->create(static::TESTED_TYPE, null, array(
204+
'false_values' => 'invalid',
205+
));
206+
}
207+
176208
public function testSubmitNull($expected = null, $norm = null, $view = null)
177209
{
178210
parent::testSubmitNull(false, false, null);

0 commit comments

Comments
 (0)