[Form] Fixed handling of expanded choice lists, checkboxes and radio buttons with empty values ("")
This commit is contained in:
parent
07e261ea9e
commit
26451201e0
@ -167,17 +167,6 @@ UPGRADE FROM 2.0 to 2.1
|
||||
colons and underscores, you can restore the old behavior by setting the
|
||||
`index_strategy` choice field option to `ChoiceList::COPY_CHOICE`.
|
||||
|
||||
* The strategy for generating the `value` HTML attribute for choices in a
|
||||
choice field has changed.
|
||||
|
||||
Instead of using the choice value, a generated integer is now stored. Again,
|
||||
take care if your JavaScript reads this value. If your choice field is a
|
||||
non-expanded single-choice field, or if the choices are guaranteed not to
|
||||
contain the empty string '' (which is the case when you added it manually
|
||||
or when the field is a single-choice field and is not required), you can
|
||||
restore the old behavior by setting the `value_strategy` choice field option
|
||||
to `ChoiceList::COPY_CHOICE`.
|
||||
|
||||
* In the choice field type's template, the structure of the `choices` variable
|
||||
has changed.
|
||||
|
||||
|
@ -442,8 +442,8 @@ class EntityTypeTest extends TypeTestCase
|
||||
$this->assertSame($entity2, $field->getData());
|
||||
$this->assertFalse($field['1']->getData());
|
||||
$this->assertTrue($field['2']->getData());
|
||||
$this->assertSame('', $field['1']->getClientData());
|
||||
$this->assertSame('1', $field['2']->getClientData());
|
||||
$this->assertNull($field['1']->getClientData());
|
||||
$this->assertSame('2', $field['2']->getClientData());
|
||||
}
|
||||
|
||||
public function testSubmitMultipleExpanded()
|
||||
@ -462,7 +462,7 @@ class EntityTypeTest extends TypeTestCase
|
||||
'property' => 'name',
|
||||
));
|
||||
|
||||
$field->bind(array('1' => '1', '3' => '3'));
|
||||
$field->bind(array('1', '3'));
|
||||
|
||||
$expected = new ArrayCollection(array($entity1, $entity3));
|
||||
|
||||
@ -472,8 +472,8 @@ class EntityTypeTest extends TypeTestCase
|
||||
$this->assertFalse($field['2']->getData());
|
||||
$this->assertTrue($field['3']->getData());
|
||||
$this->assertSame('1', $field['1']->getClientData());
|
||||
$this->assertSame('', $field['2']->getClientData());
|
||||
$this->assertSame('1', $field['3']->getClientData());
|
||||
$this->assertNull($field['2']->getClientData());
|
||||
$this->assertSame('3', $field['3']->getClientData());
|
||||
}
|
||||
|
||||
public function testOverrideChoices()
|
||||
|
@ -22,6 +22,22 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
*/
|
||||
class BooleanToStringTransformer implements DataTransformerInterface
|
||||
{
|
||||
/**
|
||||
* The value emitted upon transform if the input is true
|
||||
* @var string
|
||||
*/
|
||||
private $trueValue;
|
||||
|
||||
/**
|
||||
* Sets the value emitted upon transform if the input is true.
|
||||
*
|
||||
* @param string $trueValue
|
||||
*/
|
||||
public function __construct($trueValue)
|
||||
{
|
||||
$this->trueValue = $trueValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a Boolean into a string.
|
||||
*
|
||||
@ -34,14 +50,14 @@ class BooleanToStringTransformer implements DataTransformerInterface
|
||||
public function transform($value)
|
||||
{
|
||||
if (null === $value) {
|
||||
return '';
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!is_bool($value)) {
|
||||
throw new UnexpectedTypeException($value, 'Boolean');
|
||||
}
|
||||
|
||||
return true === $value ? '1' : '';
|
||||
return true === $value ? $this->trueValue : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -63,7 +79,7 @@ class BooleanToStringTransformer implements DataTransformerInterface
|
||||
throw new UnexpectedTypeException($value, 'string');
|
||||
}
|
||||
|
||||
return '' !== $value;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\EventListener;
|
||||
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\Event\FilterDataEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
|
||||
|
||||
/**
|
||||
* Takes care of converting the input from a list of checkboxes to a correctly
|
||||
* indexed array.
|
||||
*
|
||||
* @author Bernhard Schussek <bernhard.schussek@symfony-project.com>
|
||||
*/
|
||||
class FixCheckboxInputListener implements EventSubscriberInterface
|
||||
{
|
||||
private $choiceList;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ChoiceListInterface $choiceList
|
||||
*/
|
||||
public function __construct(ChoiceListInterface $choiceList)
|
||||
{
|
||||
$this->choiceList = $choiceList;
|
||||
}
|
||||
|
||||
public function onBindClientData(FilterDataEvent $event)
|
||||
{
|
||||
$values = (array) $event->getData();
|
||||
$indices = $this->choiceList->getIndicesForValues($values);
|
||||
|
||||
$event->setData(array_combine($indices, $values));
|
||||
}
|
||||
|
||||
static public function getSubscribedEvents()
|
||||
{
|
||||
return array(FormEvents::BIND_CLIENT_DATA => 'onBindClientData');
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ class CheckboxType extends AbstractType
|
||||
public function buildForm(FormBuilder $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->appendClientTransformer(new BooleanToStringTransformer())
|
||||
->appendClientTransformer(new BooleanToStringTransformer($options['value']))
|
||||
->setAttribute('value', $options['value'])
|
||||
;
|
||||
}
|
||||
@ -37,7 +37,7 @@ class CheckboxType extends AbstractType
|
||||
{
|
||||
$view
|
||||
->set('value', $form->getAttribute('value'))
|
||||
->set('checked', (Boolean) $form->getClientData())
|
||||
->set('checked', null !== $form->getClientData())
|
||||
;
|
||||
}
|
||||
|
||||
@ -48,6 +48,9 @@ class CheckboxType extends AbstractType
|
||||
{
|
||||
return array(
|
||||
'value' => '1',
|
||||
'empty_data' => function (FormInterface $form, $clientData) {
|
||||
return $clientData;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -14,13 +14,14 @@ namespace Symfony\Component\Form\Extension\Core\Type;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilder;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Form\Exception\FormException;
|
||||
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
|
||||
use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;
|
||||
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface;
|
||||
use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener;
|
||||
use Symfony\Component\Form\Extension\Core\EventListener\FixCheckboxInputListener;
|
||||
use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToBooleanArrayTransformer;
|
||||
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer;
|
||||
@ -81,7 +82,10 @@ class ChoiceType extends AbstractType
|
||||
|
||||
if ($options['expanded']) {
|
||||
if ($options['multiple']) {
|
||||
$builder->appendClientTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list']));
|
||||
$builder
|
||||
->appendClientTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list']))
|
||||
->addEventSubscriber(new FixCheckboxInputListener($options['choice_list']), 10)
|
||||
;
|
||||
} else {
|
||||
$builder
|
||||
->appendClientTransformer(new ChoiceToBooleanArrayTransformer($options['choice_list']))
|
||||
@ -155,7 +159,7 @@ class ChoiceType extends AbstractType
|
||||
'choice_list' => null,
|
||||
'choices' => null,
|
||||
'preferred_choices' => array(),
|
||||
'value_strategy' => ChoiceList::GENERATE,
|
||||
'value_strategy' => ChoiceList::COPY_CHOICE,
|
||||
'index_strategy' => ChoiceList::GENERATE,
|
||||
'empty_data' => $multiple || $expanded ? array() : '',
|
||||
'empty_value' => $multiple || $expanded || !isset($options['empty_value']) ? null : '',
|
||||
|
@ -470,7 +470,11 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_scalar($clientData) || null === $clientData) {
|
||||
// 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($clientData)) {
|
||||
$clientData = (string) $clientData;
|
||||
}
|
||||
|
||||
@ -522,11 +526,13 @@ class Form implements \IteratorAggregate, FormInterface
|
||||
}
|
||||
|
||||
if (null === $clientData || '' === $clientData) {
|
||||
$clientData = $this->emptyData;
|
||||
$emptyData = $this->emptyData;
|
||||
|
||||
if ($clientData instanceof \Closure) {
|
||||
$clientData = $clientData($this);
|
||||
if ($emptyData instanceof \Closure) {
|
||||
$emptyData = $emptyData($this, $clientData);
|
||||
}
|
||||
|
||||
$clientData = $emptyData;
|
||||
}
|
||||
|
||||
// Merge form data from children into existing client data
|
||||
|
@ -330,8 +330,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@name="name"]
|
||||
[@required="required"]
|
||||
[
|
||||
./option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=2]
|
||||
'
|
||||
@ -352,9 +352,9 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@name="name"]
|
||||
[@required="required"]
|
||||
[
|
||||
./option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
/following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"]
|
||||
/following-sibling::option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
]
|
||||
[count(./option)=3]
|
||||
'
|
||||
@ -376,8 +376,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@name="name"]
|
||||
[@required="required"]
|
||||
[
|
||||
./option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
/following-sibling::option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
/following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
]
|
||||
[count(./option)=2]
|
||||
'
|
||||
@ -398,9 +398,9 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@name="name"]
|
||||
[@required="required"]
|
||||
[
|
||||
./option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
/following-sibling::option[@disabled="disabled"][not(@selected)][.=""]
|
||||
/following-sibling::option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
]
|
||||
[count(./option)=3]
|
||||
'
|
||||
@ -438,8 +438,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[not(@required)]
|
||||
[
|
||||
./option[@value=""][.="[trans][/trans]"]
|
||||
/following-sibling::option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
/following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=3]
|
||||
'
|
||||
@ -461,8 +461,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[not(@required)]
|
||||
[
|
||||
./option[@value=""][.="[trans][/trans]"]
|
||||
/following-sibling::option[@value="0"][not(@selected)][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
/following-sibling::option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=3]
|
||||
'
|
||||
@ -485,8 +485,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[not(@required)]
|
||||
[
|
||||
./option[@value=""][not(@selected)][.="[trans]Select&Anything&Not&Me[/trans]"]
|
||||
/following-sibling::option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
/following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=3]
|
||||
'
|
||||
@ -509,8 +509,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@required="required"]
|
||||
[
|
||||
./option[@value=""][.="[trans]Test&Me[/trans]"]
|
||||
/following-sibling::option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
/following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=3]
|
||||
'
|
||||
@ -532,8 +532,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@required="required"]
|
||||
[
|
||||
./option[@value=""][.="[trans][/trans]"]
|
||||
/following-sibling::option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
/following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=3]
|
||||
'
|
||||
@ -556,13 +556,13 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@name="name"]
|
||||
[./optgroup[@label="[trans]Group&1[/trans]"]
|
||||
[
|
||||
./option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=2]
|
||||
]
|
||||
[./optgroup[@label="[trans]Group&2[/trans]"]
|
||||
[./option[@value="2"][not(@selected)][.="[trans]Choice&C[/trans]"]]
|
||||
[./option[@value="&c"][not(@selected)][.="[trans]Choice&C[/trans]"]]
|
||||
[count(./option)=1]
|
||||
]
|
||||
[count(./optgroup)=2]
|
||||
@ -583,8 +583,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@name="name[]"]
|
||||
[@multiple="multiple"]
|
||||
[
|
||||
./option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=2]
|
||||
'
|
||||
@ -605,8 +605,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@name="name[]"]
|
||||
[@multiple="multiple"]
|
||||
[
|
||||
./option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=2]
|
||||
'
|
||||
@ -627,8 +627,8 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
[@name="name[]"]
|
||||
[@multiple="multiple"]
|
||||
[
|
||||
./option[@value="0"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="1"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./option)=2]
|
||||
'
|
||||
@ -646,9 +646,9 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertWidgetMatchesXpath($form->createView(), array(),
|
||||
'/div
|
||||
[
|
||||
./input[@type="radio"][@name="name"][@id="name_0"][@value="0"][@checked]
|
||||
./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked]
|
||||
/following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"]
|
||||
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="1"][not(@checked)]
|
||||
/following-sibling::input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)]
|
||||
/following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"]
|
||||
]
|
||||
[count(./input)=2]
|
||||
|
@ -15,11 +15,13 @@ use Symfony\Component\Form\Extension\Core\DataTransformer\BooleanToStringTransfo
|
||||
|
||||
class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
const TRUE_VALUE = '1';
|
||||
|
||||
protected $transformer;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->transformer = new BooleanToStringTransformer();
|
||||
$this->transformer = new BooleanToStringTransformer(self::TRUE_VALUE);
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
@ -29,9 +31,9 @@ class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testTransform()
|
||||
{
|
||||
$this->assertEquals('1', $this->transformer->transform(true));
|
||||
$this->assertEquals('', $this->transformer->transform(false));
|
||||
$this->assertSame('', $this->transformer->transform(null));
|
||||
$this->assertEquals(self::TRUE_VALUE, $this->transformer->transform(true));
|
||||
$this->assertNull($this->transformer->transform(false));
|
||||
$this->assertNull($this->transformer->transform(null));
|
||||
}
|
||||
|
||||
public function testTransformExpectsBoolean()
|
||||
@ -50,9 +52,9 @@ class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testReverseTransform()
|
||||
{
|
||||
$this->assertTrue($this->transformer->reverseTransform('1'));
|
||||
$this->assertTrue($this->transformer->reverseTransform('0'));
|
||||
$this->assertFalse($this->transformer->reverseTransform(''));
|
||||
$this->assertTrue($this->transformer->reverseTransform(self::TRUE_VALUE));
|
||||
$this->assertTrue($this->transformer->reverseTransform('foobar'));
|
||||
$this->assertTrue($this->transformer->reverseTransform(''));
|
||||
$this->assertFalse($this->transformer->reverseTransform(null));
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,15 @@ class CheckboxTypeTest extends TypeTestCase
|
||||
$this->assertTrue($view->get('checked'));
|
||||
}
|
||||
|
||||
public function testCheckedIfDataTrueWithEmptyValue()
|
||||
{
|
||||
$form = $this->factory->create('checkbox', null, array('value' => ''));
|
||||
$form->setData(true);
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertTrue($view->get('checked'));
|
||||
}
|
||||
|
||||
public function testNotCheckedIfDataFalse()
|
||||
{
|
||||
$form = $this->factory->create('checkbox');
|
||||
@ -41,8 +50,63 @@ class CheckboxTypeTest extends TypeTestCase
|
||||
$this->assertFalse($view->get('checked'));
|
||||
}
|
||||
|
||||
public function testBindWithValueChecked()
|
||||
{
|
||||
$form = $this->factory->create('checkbox', null, array(
|
||||
'value' => 'foobar',
|
||||
));
|
||||
$form->bind('foobar');
|
||||
|
||||
$this->assertTrue($form->getData());
|
||||
$this->assertEquals('foobar', $form->getClientData());
|
||||
}
|
||||
|
||||
public function testBindWithRandomValueChecked()
|
||||
{
|
||||
$form = $this->factory->create('checkbox', null, array(
|
||||
'value' => 'foobar',
|
||||
));
|
||||
$form->bind('krixikraxi');
|
||||
|
||||
$this->assertTrue($form->getData());
|
||||
$this->assertEquals('foobar', $form->getClientData());
|
||||
}
|
||||
|
||||
public function testBindWithValueUnchecked()
|
||||
{
|
||||
$form = $this->factory->create('checkbox', null, array(
|
||||
'value' => 'foobar',
|
||||
));
|
||||
$form->bind(null);
|
||||
|
||||
$this->assertFalse($form->getData());
|
||||
$this->assertNull($form->getClientData());
|
||||
}
|
||||
|
||||
public function testBindWithEmptyValueChecked()
|
||||
{
|
||||
$form = $this->factory->create('checkbox', null, array(
|
||||
'value' => '',
|
||||
));
|
||||
$form->bind('');
|
||||
|
||||
$this->assertTrue($form->getData());
|
||||
$this->assertSame('', $form->getClientData());
|
||||
}
|
||||
|
||||
public function testBindWithEmptyValueUnchecked()
|
||||
{
|
||||
$form = $this->factory->create('checkbox', null, array(
|
||||
'value' => '',
|
||||
));
|
||||
$form->bind(null);
|
||||
|
||||
$this->assertFalse($form->getData());
|
||||
$this->assertNull($form->getClientData());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider proviceTransformedData
|
||||
* @dataProvider provideTransformedData
|
||||
*/
|
||||
public function testTransformedData($data, $expected)
|
||||
{
|
||||
@ -60,7 +124,7 @@ class CheckboxTypeTest extends TypeTestCase
|
||||
|
||||
$form = $this->builder
|
||||
->create('expedited_shipping', 'checkbox')
|
||||
->prependClientTransformer($transformer)
|
||||
->prependNormTransformer($transformer)
|
||||
->getForm();
|
||||
$form->setData($data);
|
||||
$view = $form->createView();
|
||||
@ -68,7 +132,7 @@ class CheckboxTypeTest extends TypeTestCase
|
||||
$this->assertEquals($expected, $view->get('checked'));
|
||||
}
|
||||
|
||||
public function proviceTransformedData()
|
||||
public function provideTransformedData()
|
||||
{
|
||||
return array(
|
||||
array('expedited', true),
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
|
||||
|
||||
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
|
||||
|
||||
use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList;
|
||||
use Symfony\Component\Form\Extension\Core\View\ChoiceView;
|
||||
|
||||
@ -34,14 +36,6 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
|
||||
private $objectChoices;
|
||||
|
||||
private $stringButNumericChoices = array(
|
||||
'0' => 'Bernhard',
|
||||
'1' => 'Fabien',
|
||||
'2' => 'Kris',
|
||||
'3' => 'Jon',
|
||||
'4' => 'Roman',
|
||||
);
|
||||
|
||||
protected $groupedChoices = array(
|
||||
'Symfony' => array(
|
||||
'a' => 'Bernhard',
|
||||
@ -183,10 +177,10 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
'choices' => $this->choices,
|
||||
));
|
||||
|
||||
$form->bind('1');
|
||||
$form->bind('b');
|
||||
|
||||
$this->assertEquals('b', $form->getData());
|
||||
$this->assertEquals('1', $form->getClientData());
|
||||
$this->assertEquals('b', $form->getClientData());
|
||||
}
|
||||
|
||||
public function testBindSingleNonExpandedObjectChoices()
|
||||
@ -220,10 +214,10 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
'choices' => $this->choices,
|
||||
));
|
||||
|
||||
$form->bind(array('0', '1'));
|
||||
$form->bind(array('a', 'b'));
|
||||
|
||||
$this->assertEquals(array('a', 'b'), $form->getData());
|
||||
$this->assertEquals(array('0', '1'), $form->getClientData());
|
||||
$this->assertEquals(array('a', 'b'), $form->getClientData());
|
||||
}
|
||||
|
||||
public function testBindMultipleNonExpandedObjectChoices()
|
||||
@ -256,7 +250,7 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
'choices' => $this->choices,
|
||||
));
|
||||
|
||||
$form->bind('1');
|
||||
$form->bind('b');
|
||||
|
||||
$this->assertSame('b', $form->getData());
|
||||
$this->assertFalse($form[0]->getData());
|
||||
@ -264,11 +258,34 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
$this->assertFalse($form[2]->getData());
|
||||
$this->assertFalse($form[3]->getData());
|
||||
$this->assertFalse($form[4]->getData());
|
||||
$this->assertSame('', $form[0]->getClientData());
|
||||
$this->assertSame('1', $form[1]->getClientData());
|
||||
$this->assertSame('', $form[2]->getClientData());
|
||||
$this->assertSame('', $form[3]->getClientData());
|
||||
$this->assertSame('', $form[4]->getClientData());
|
||||
$this->assertNull($form[0]->getClientData());
|
||||
$this->assertSame('b', $form[1]->getClientData());
|
||||
$this->assertNull($form[2]->getClientData());
|
||||
$this->assertNull($form[3]->getClientData());
|
||||
$this->assertNull($form[4]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindSingleExpandedNothingChecked()
|
||||
{
|
||||
$form = $this->factory->create('choice', null, array(
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'choices' => $this->choices,
|
||||
));
|
||||
|
||||
$form->bind(null);
|
||||
|
||||
$this->assertSame(null, $form->getData());
|
||||
$this->assertFalse($form[0]->getData());
|
||||
$this->assertFalse($form[1]->getData());
|
||||
$this->assertFalse($form[2]->getData());
|
||||
$this->assertFalse($form[3]->getData());
|
||||
$this->assertFalse($form[4]->getData());
|
||||
$this->assertNull($form[0]->getClientData());
|
||||
$this->assertNull($form[1]->getClientData());
|
||||
$this->assertNull($form[2]->getClientData());
|
||||
$this->assertNull($form[3]->getClientData());
|
||||
$this->assertNull($form[4]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindSingleExpandedWithFalseDoesNotHaveExtraFields()
|
||||
@ -292,17 +309,17 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
'expanded' => true,
|
||||
'choices' => array(
|
||||
'' => 'Empty',
|
||||
'1' => 'Not empty',
|
||||
1 => 'Not empty',
|
||||
),
|
||||
));
|
||||
|
||||
$form->bind('0');
|
||||
$form->bind('');
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertTrue($form[0]->getData());
|
||||
$this->assertFalse($form[1]->getData());
|
||||
$this->assertSame('1', $form[0]->getClientData());
|
||||
$this->assertSame('', $form[1]->getClientData());
|
||||
$this->assertSame('', $form[0]->getClientData());
|
||||
$this->assertNull($form[1]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindSingleExpandedObjectChoices()
|
||||
@ -329,11 +346,11 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
$this->assertFalse($form[2]->getData());
|
||||
$this->assertFalse($form[3]->getData());
|
||||
$this->assertFalse($form[4]->getData());
|
||||
$this->assertSame('', $form[0]->getClientData());
|
||||
$this->assertSame('1', $form[1]->getClientData());
|
||||
$this->assertSame('', $form[2]->getClientData());
|
||||
$this->assertSame('', $form[3]->getClientData());
|
||||
$this->assertSame('', $form[4]->getClientData());
|
||||
$this->assertNull($form[0]->getClientData());
|
||||
$this->assertSame('2', $form[1]->getClientData());
|
||||
$this->assertNull($form[2]->getClientData());
|
||||
$this->assertNull($form[3]->getClientData());
|
||||
$this->assertNull($form[4]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindSingleExpandedNumericChoices()
|
||||
@ -352,34 +369,11 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
$this->assertFalse($form[2]->getData());
|
||||
$this->assertFalse($form[3]->getData());
|
||||
$this->assertFalse($form[4]->getData());
|
||||
$this->assertSame('', $form[0]->getClientData());
|
||||
$this->assertNull($form[0]->getClientData());
|
||||
$this->assertSame('1', $form[1]->getClientData());
|
||||
$this->assertSame('', $form[2]->getClientData());
|
||||
$this->assertSame('', $form[3]->getClientData());
|
||||
$this->assertSame('', $form[4]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindSingleExpandedStringsButNumericChoices()
|
||||
{
|
||||
$form = $this->factory->create('choice', null, array(
|
||||
'multiple' => false,
|
||||
'expanded' => true,
|
||||
'choices' => $this->stringButNumericChoices,
|
||||
));
|
||||
|
||||
$form->bind('1');
|
||||
|
||||
$this->assertSame(1, $form->getData());
|
||||
$this->assertFalse($form[0]->getData());
|
||||
$this->assertTrue($form[1]->getData());
|
||||
$this->assertFalse($form[2]->getData());
|
||||
$this->assertFalse($form[3]->getData());
|
||||
$this->assertFalse($form[4]->getData());
|
||||
$this->assertSame('', $form[0]->getClientData());
|
||||
$this->assertSame('1', $form[1]->getClientData());
|
||||
$this->assertSame('', $form[2]->getClientData());
|
||||
$this->assertSame('', $form[3]->getClientData());
|
||||
$this->assertSame('', $form[4]->getClientData());
|
||||
$this->assertNull($form[2]->getClientData());
|
||||
$this->assertNull($form[3]->getClientData());
|
||||
$this->assertNull($form[4]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindMultipleExpanded()
|
||||
@ -390,19 +384,43 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
'choices' => $this->choices,
|
||||
));
|
||||
|
||||
$form->bind(array(0 => 'a', 1 => 'b'));
|
||||
$form->bind(array('a', 'c'));
|
||||
|
||||
$this->assertSame(array(0 => 'a', 1 => 'b'), $form->getData());
|
||||
$this->assertSame(array('a', 'c'), $form->getData());
|
||||
$this->assertTrue($form[0]->getData());
|
||||
$this->assertTrue($form[1]->getData());
|
||||
$this->assertFalse($form[2]->getData());
|
||||
$this->assertFalse($form[1]->getData());
|
||||
$this->assertTrue($form[2]->getData());
|
||||
$this->assertFalse($form[3]->getData());
|
||||
$this->assertFalse($form[4]->getData());
|
||||
$this->assertSame('1', $form[0]->getClientData());
|
||||
$this->assertSame('1', $form[1]->getClientData());
|
||||
$this->assertSame('', $form[2]->getClientData());
|
||||
$this->assertSame('', $form[3]->getClientData());
|
||||
$this->assertSame('', $form[4]->getClientData());
|
||||
$this->assertSame('a', $form[0]->getClientData());
|
||||
$this->assertNull($form[1]->getClientData());
|
||||
$this->assertSame('c', $form[2]->getClientData());
|
||||
$this->assertNull($form[3]->getClientData());
|
||||
$this->assertNull($form[4]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindMultipleExpandedWithEmptyField()
|
||||
{
|
||||
$form = $this->factory->create('choice', null, array(
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'choices' => array(
|
||||
'' => 'Empty',
|
||||
1 => 'Not Empty',
|
||||
2 => 'Not Empty 2',
|
||||
),
|
||||
'value_strategy' => ChoiceList::COPY_CHOICE,
|
||||
));
|
||||
|
||||
$form->bind(array('', '2'));
|
||||
|
||||
$this->assertSame(array('', 2), $form->getData());
|
||||
$this->assertTrue($form[0]->getData());
|
||||
$this->assertFalse($form[1]->getData());
|
||||
$this->assertTrue($form[2]->getData());
|
||||
$this->assertSame('', $form[0]->getClientData());
|
||||
$this->assertNull($form[1]->getClientData());
|
||||
$this->assertSame('2', $form[2]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindMultipleExpandedObjectChoices()
|
||||
@ -421,7 +439,7 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
),
|
||||
));
|
||||
|
||||
$form->bind(array(0 => '1', 1 => '2'));
|
||||
$form->bind(array('1', '2'));
|
||||
|
||||
$this->assertSame(array($this->objectChoices[0], $this->objectChoices[1]), $form->getData());
|
||||
$this->assertTrue($form[0]->getData());
|
||||
@ -430,10 +448,10 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
$this->assertFalse($form[3]->getData());
|
||||
$this->assertFalse($form[4]->getData());
|
||||
$this->assertSame('1', $form[0]->getClientData());
|
||||
$this->assertSame('1', $form[1]->getClientData());
|
||||
$this->assertSame('', $form[2]->getClientData());
|
||||
$this->assertSame('', $form[3]->getClientData());
|
||||
$this->assertSame('', $form[4]->getClientData());
|
||||
$this->assertSame('2', $form[1]->getClientData());
|
||||
$this->assertNull($form[2]->getClientData());
|
||||
$this->assertNull($form[3]->getClientData());
|
||||
$this->assertNull($form[4]->getClientData());
|
||||
}
|
||||
|
||||
public function testBindMultipleExpandedNumericChoices()
|
||||
@ -444,7 +462,7 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
'choices' => $this->numericChoices,
|
||||
));
|
||||
|
||||
$form->bind(array(1 => '1', 2 => '2'));
|
||||
$form->bind(array('1', '2'));
|
||||
|
||||
$this->assertSame(array(1, 2), $form->getData());
|
||||
$this->assertFalse($form[0]->getData());
|
||||
@ -452,11 +470,11 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
$this->assertTrue($form[2]->getData());
|
||||
$this->assertFalse($form[3]->getData());
|
||||
$this->assertFalse($form[4]->getData());
|
||||
$this->assertSame('', $form[0]->getClientData());
|
||||
$this->assertNull($form[0]->getClientData());
|
||||
$this->assertSame('1', $form[1]->getClientData());
|
||||
$this->assertSame('1', $form[2]->getClientData());
|
||||
$this->assertSame('', $form[3]->getClientData());
|
||||
$this->assertSame('', $form[4]->getClientData());
|
||||
$this->assertSame('2', $form[2]->getClientData());
|
||||
$this->assertNull($form[3]->getClientData());
|
||||
$this->assertNull($form[4]->getClientData());
|
||||
}
|
||||
|
||||
/*
|
||||
@ -598,10 +616,10 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertEquals(array(
|
||||
new ChoiceView('0', 'A'),
|
||||
new ChoiceView('1', 'B'),
|
||||
new ChoiceView('2', 'C'),
|
||||
new ChoiceView('3', 'D'),
|
||||
new ChoiceView('a', 'A'),
|
||||
new ChoiceView('b', 'B'),
|
||||
new ChoiceView('c', 'C'),
|
||||
new ChoiceView('d', 'D'),
|
||||
), $view->get('choices'));
|
||||
}
|
||||
|
||||
@ -615,12 +633,12 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertEquals(array(
|
||||
0 => new ChoiceView('0', 'A'),
|
||||
2 => new ChoiceView('2', 'C'),
|
||||
0 => new ChoiceView('a', 'A'),
|
||||
2 => new ChoiceView('c', 'C'),
|
||||
), $view->get('choices'));
|
||||
$this->assertEquals(array(
|
||||
1 => new ChoiceView('1', 'B'),
|
||||
3 => new ChoiceView('3', 'D'),
|
||||
1 => new ChoiceView('b', 'B'),
|
||||
3 => new ChoiceView('d', 'D'),
|
||||
), $view->get('preferred_choices'));
|
||||
}
|
||||
|
||||
@ -634,19 +652,19 @@ class ChoiceTypeTest extends TypeTestCase
|
||||
|
||||
$this->assertEquals(array(
|
||||
'Symfony' => array(
|
||||
0 => new ChoiceView('0', 'Bernhard'),
|
||||
2 => new ChoiceView('2', 'Kris'),
|
||||
0 => new ChoiceView('a', 'Bernhard'),
|
||||
2 => new ChoiceView('c', 'Kris'),
|
||||
),
|
||||
'Doctrine' => array(
|
||||
4 => new ChoiceView('4', 'Roman'),
|
||||
4 => new ChoiceView('e', 'Roman'),
|
||||
),
|
||||
), $view->get('choices'));
|
||||
$this->assertEquals(array(
|
||||
'Symfony' => array(
|
||||
1 => new ChoiceView('1', 'Fabien'),
|
||||
1 => new ChoiceView('b', 'Fabien'),
|
||||
),
|
||||
'Doctrine' => array(
|
||||
3 => new ChoiceView('3', 'Jon'),
|
||||
3 => new ChoiceView('d', 'Jon'),
|
||||
),
|
||||
), $view->get('preferred_choices'));
|
||||
}
|
||||
|
Reference in New Issue
Block a user