diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index a7a057dd09..1b3b0f3120 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -488,11 +488,14 @@ class Form implements \IteratorAggregate, FormInterface $this->setData($this->config->getData()); } + // Treat false as NULL to support binding false to checkboxes. // Don't convert NULL to a string here in order to determine later // whether an empty value has been submitted or whether no value has // been submitted at all. This is important for processing checkboxes // and radio buttons with empty values. - if (is_scalar($submittedData)) { + if (false === $submittedData) { + $submittedData = null; + } elseif (is_scalar($submittedData)) { $submittedData = (string) $submittedData; } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php index 304958f768..d4b7e8c086 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -105,6 +105,28 @@ class CheckboxTypeTest extends \Symfony\Component\Form\Test\TypeTestCase $this->assertNull($form->getViewData()); } + public function testBindWithEmptyValueAndFalseUnchecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => '', + )); + $form->bind(false); + + $this->assertFalse($form->getData()); + $this->assertNull($form->getViewData()); + } + + public function testBindWithEmptyValueAndTrueChecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => '', + )); + $form->bind(true); + + $this->assertTrue($form->getData()); + $this->assertSame('', $form->getViewData()); + } + /** * @dataProvider provideTransformedData */ diff --git a/src/Symfony/Component/Form/Tests/SimpleFormTest.php b/src/Symfony/Component/Form/Tests/SimpleFormTest.php index 09dea71d25..c80a03005e 100644 --- a/src/Symfony/Component/Form/Tests/SimpleFormTest.php +++ b/src/Symfony/Component/Form/Tests/SimpleFormTest.php @@ -96,6 +96,28 @@ class SimpleFormTest extends AbstractFormTest $form->bind('foobar'); } + // https://github.com/symfony/symfony/pull/7789 + public function testFalseIsConvertedToNull() + { + $mock = $this->getMockBuilder('\stdClass') + ->setMethods(array('preBind')) + ->getMock(); + $mock->expects($this->once()) + ->method('preBind') + ->with($this->callback(function ($event) { + return null === $event->getData(); + })); + + $config = new FormConfigBuilder('name', null, $this->dispatcher); + $config->addEventListener(FormEvents::PRE_BIND, array($mock, 'preBind')); + $form = new Form($config); + + $form->bind(false); + + $this->assertTrue($form->isValid()); + $this->assertNull($form->getData()); + } + /** * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException */