Merge branch '2.7' into 2.8
* 2.7: [Form] refactor CheckboxListMapper and RadioListMapper Revert "[Form] refactor `RadioListMapper::mapDataToForm()`"
This commit is contained in:
commit
5c235428d2
@ -287,7 +287,7 @@ class EntityTypeTest extends TypeTestCase
|
||||
$field->submit(null);
|
||||
|
||||
$this->assertNull($field->getData());
|
||||
$this->assertNull($field->getViewData());
|
||||
$this->assertSame('', $field->getViewData(), 'View data is always a string');
|
||||
}
|
||||
|
||||
public function testSubmitSingleNonExpandedNull()
|
||||
|
@ -23,7 +23,7 @@
|
||||
"require-dev": {
|
||||
"symfony/stopwatch": "~2.2|~3.0.0",
|
||||
"symfony/dependency-injection": "~2.2|~3.0.0",
|
||||
"symfony/form": "~2.8|~3.0.0",
|
||||
"symfony/form": "~2.8.5|~3.0.5",
|
||||
"symfony/http-kernel": "~2.2|~3.0.0",
|
||||
"symfony/property-access": "~2.3|~3.0.0",
|
||||
"symfony/property-info": "~2.8|3.0",
|
||||
|
@ -11,9 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\DataMapper;
|
||||
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||
use Symfony\Component\Form\DataMapperInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
|
||||
/**
|
||||
* Maps choices to/from checkbox forms.
|
||||
@ -26,16 +25,6 @@ use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
*/
|
||||
class CheckboxListMapper implements DataMapperInterface
|
||||
{
|
||||
/**
|
||||
* @var ChoiceListInterface
|
||||
*/
|
||||
private $choiceList;
|
||||
|
||||
public function __construct(ChoiceListInterface $choiceList)
|
||||
{
|
||||
$this->choiceList = $choiceList;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -46,22 +35,12 @@ class CheckboxListMapper implements DataMapperInterface
|
||||
}
|
||||
|
||||
if (!is_array($choices)) {
|
||||
throw new TransformationFailedException('Expected an array.');
|
||||
}
|
||||
|
||||
try {
|
||||
$valueMap = array_flip($this->choiceList->getValuesForChoices($choices));
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException(
|
||||
'Can not read the choices from the choice list.',
|
||||
$e->getCode(),
|
||||
$e
|
||||
);
|
||||
throw new UnexpectedTypeException($choices, 'array');
|
||||
}
|
||||
|
||||
foreach ($checkboxes as $checkbox) {
|
||||
$value = $checkbox->getConfig()->getOption('value');
|
||||
$checkbox->setData(isset($valueMap[$value]) ? true : false);
|
||||
$checkbox->setData(in_array($value, $choices, true));
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,6 +49,10 @@ class CheckboxListMapper implements DataMapperInterface
|
||||
*/
|
||||
public function mapFormsToData($checkboxes, &$choices)
|
||||
{
|
||||
if (!is_array($choices)) {
|
||||
throw new UnexpectedTypeException($choices, 'array');
|
||||
}
|
||||
|
||||
$values = array();
|
||||
|
||||
foreach ($checkboxes as $checkbox) {
|
||||
@ -79,14 +62,6 @@ class CheckboxListMapper implements DataMapperInterface
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$choices = $this->choiceList->getChoicesForValues($values);
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException(
|
||||
'Can not read the values from the choice list.',
|
||||
$e->getCode(),
|
||||
$e
|
||||
);
|
||||
}
|
||||
$choices = $values;
|
||||
}
|
||||
}
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Form\Extension\Core\DataMapper;
|
||||
|
||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||
use Symfony\Component\Form\DataMapperInterface;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
|
||||
/**
|
||||
* Maps choices to/from radio forms.
|
||||
@ -25,24 +25,18 @@ use Symfony\Component\Form\DataMapperInterface;
|
||||
*/
|
||||
class RadioListMapper implements DataMapperInterface
|
||||
{
|
||||
/**
|
||||
* @var ChoiceListInterface
|
||||
*/
|
||||
private $choiceList;
|
||||
|
||||
public function __construct(ChoiceListInterface $choiceList)
|
||||
{
|
||||
$this->choiceList = $choiceList;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mapDataToForms($data, $radios)
|
||||
public function mapDataToForms($choice, $radios)
|
||||
{
|
||||
if (!is_string($choice)) {
|
||||
throw new UnexpectedTypeException($choice, 'string');
|
||||
}
|
||||
|
||||
foreach ($radios as $radio) {
|
||||
$value = $radio->getConfig()->getOption('value');
|
||||
$radio->setData($value === $data ? true : false);
|
||||
$radio->setData($choice === $value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,6 +45,10 @@ class RadioListMapper implements DataMapperInterface
|
||||
*/
|
||||
public function mapFormsToData($radios, &$choice)
|
||||
{
|
||||
if (null !== $choice && !is_string($choice)) {
|
||||
throw new UnexpectedTypeException($choice, 'null or string');
|
||||
}
|
||||
|
||||
$choice = null;
|
||||
|
||||
foreach ($radios as $radio) {
|
||||
@ -59,8 +57,7 @@ class RadioListMapper implements DataMapperInterface
|
||||
return;
|
||||
}
|
||||
|
||||
$value = $radio->getConfig()->getOption('value');
|
||||
$choice = current($this->choiceList->getChoicesForValues(array($value)));
|
||||
$choice = $radio->getConfig()->getOption('value');
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -60,9 +60,7 @@ class ChoiceType extends AbstractType
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
if ($options['expanded']) {
|
||||
$builder->setDataMapper($options['multiple']
|
||||
? new CheckboxListMapper($options['choice_list'])
|
||||
: new RadioListMapper($options['choice_list']));
|
||||
$builder->setDataMapper($options['multiple'] ? new CheckboxListMapper() : new RadioListMapper());
|
||||
|
||||
// Initialize all choices before doing the index check below.
|
||||
// This helps in cases where index checks are optimized for non
|
||||
@ -133,30 +131,13 @@ class ChoiceType extends AbstractType
|
||||
|
||||
$event->setData($data);
|
||||
});
|
||||
}
|
||||
|
||||
if (!$options['multiple']) {
|
||||
// For radio lists, transform empty arrays to null
|
||||
// This is kind of a hack necessary because the RadioListMapper
|
||||
// is not invoked for forms without choices
|
||||
$builder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) {
|
||||
if (array() === $event->getData()) {
|
||||
$event->setData(null);
|
||||
}
|
||||
});
|
||||
// For radio lists, pre selection of the choice needs to pre set data
|
||||
// with the string value so it can be matched in
|
||||
// {@link \Symfony\Component\Form\Extension\Core\DataMapper\RadioListMapper::mapDataToForms()}
|
||||
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
|
||||
$choiceList = $event->getForm()->getConfig()->getOption('choice_list');
|
||||
$value = current($choiceList->getValuesForChoices(array($event->getData())));
|
||||
$event->setData((string) $value);
|
||||
});
|
||||
}
|
||||
} elseif ($options['multiple']) {
|
||||
// <select> tag with "multiple" option
|
||||
if ($options['multiple']) {
|
||||
// <select> tag with "multiple" option or list of checkbox inputs
|
||||
$builder->addViewTransformer(new ChoicesToValuesTransformer($options['choice_list']));
|
||||
} else {
|
||||
// <select> tag without "multiple" option
|
||||
// <select> tag without "multiple" option or list of radio inputs
|
||||
$builder->addViewTransformer(new ChoiceToValueTransformer($options['choice_list']));
|
||||
}
|
||||
|
||||
@ -255,7 +236,11 @@ class ChoiceType extends AbstractType
|
||||
$choiceListFactory = $this->choiceListFactory;
|
||||
|
||||
$emptyData = function (Options $options) {
|
||||
if ($options['multiple'] || $options['expanded']) {
|
||||
if ($options['expanded'] && !$options['multiple']) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($options['multiple']) {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,12 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
'n/a' => '',
|
||||
);
|
||||
|
||||
private $booleanChoicesWithNull = array(
|
||||
'Yes' => true,
|
||||
'No' => false,
|
||||
'n/a' => null,
|
||||
);
|
||||
|
||||
private $numericChoicesFlipped = array(
|
||||
0 => 'Bernhard',
|
||||
1 => 'Fabien',
|
||||
@ -194,6 +200,19 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$this->assertTrue($view->children[2]->vars['checked'], 'Empty value should be pre selected');
|
||||
}
|
||||
|
||||
public function testExpandedChoiceListWithBooleanAndNullValues()
|
||||
{
|
||||
$view = $this->factory->create('choice', null, array(
|
||||
'choices' => $this->booleanChoicesWithNull,
|
||||
'choices_as_values' => true,
|
||||
'expanded' => true,
|
||||
))->createView();
|
||||
|
||||
$this->assertFalse($view->children[0]->vars['checked'], 'True value should not be pre selected');
|
||||
$this->assertFalse($view->children[1]->vars['checked'], 'False value should not be pre selected');
|
||||
$this->assertTrue($view->children[2]->vars['checked'], 'Empty value should be pre selected');
|
||||
}
|
||||
|
||||
public function testExpandedChoiceListWithScalarValuesAndFalseAsPreSetData()
|
||||
{
|
||||
$view = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\ChoiceType', false, array(
|
||||
@ -208,6 +227,19 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$this->assertFalse($view->children[2]->vars['checked'], 'Empty value should not be pre selected');
|
||||
}
|
||||
|
||||
public function testExpandedChoiceListWithBooleanAndNullValuesAndFalseAsPreSetData()
|
||||
{
|
||||
$view = $this->factory->create('choice', false, array(
|
||||
'choices' => $this->booleanChoicesWithNull,
|
||||
'choices_as_values' => true,
|
||||
'expanded' => true,
|
||||
))->createView();
|
||||
|
||||
$this->assertFalse($view->children[0]->vars['checked'], 'True value should not be pre selected');
|
||||
$this->assertTrue($view->children[1]->vars['checked'], 'False value should be pre selected');
|
||||
$this->assertFalse($view->children[2]->vars['checked'], 'Null value should not be pre selected');
|
||||
}
|
||||
|
||||
public function testPlaceholderPresentOnNonRequiredExpandedSingleChoice()
|
||||
{
|
||||
$form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array(
|
||||
@ -330,7 +362,7 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertSame('', $view->vars['value'], 'Value should be empty');
|
||||
$this->assertSame('', $view->vars['value'], 'Value should be an empty string');
|
||||
$this->assertSame('1', $view->vars['choices'][0]->value);
|
||||
$this->assertSame('0', $view->vars['choices'][1]->value, 'Choice "false" should have "0" as value');
|
||||
$this->assertFalse($view->children[1]->vars['checked'], 'Choice "false" should not be selected');
|
||||
@ -951,8 +983,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit(null);
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
|
||||
$this->assertFalse($form[0]->getData());
|
||||
@ -983,8 +1015,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit(null);
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
}
|
||||
|
||||
@ -1001,8 +1033,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit('');
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
|
||||
$this->assertFalse($form[0]->getData());
|
||||
@ -1033,8 +1065,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit('');
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
}
|
||||
|
||||
@ -1051,8 +1083,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit(false);
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
|
||||
$this->assertFalse($form[0]->getData());
|
||||
@ -1083,8 +1115,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit(false);
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
}
|
||||
|
||||
@ -1101,8 +1133,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit(null);
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
|
||||
$this->assertTrue($form['placeholder']->getData());
|
||||
@ -1135,8 +1167,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit(null);
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
}
|
||||
|
||||
@ -1153,8 +1185,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit('');
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
|
||||
$this->assertTrue($form['placeholder']->getData());
|
||||
@ -1187,8 +1219,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit('');
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
}
|
||||
|
||||
@ -1205,8 +1237,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit(false);
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
|
||||
$this->assertTrue($form['placeholder']->getData());
|
||||
@ -1239,8 +1271,8 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
$form->submit(false);
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertNull($form->getViewData());
|
||||
$this->assertEmpty($form->getExtraData());
|
||||
$this->assertSame('', $form->getViewData(), 'View data should always be a string');
|
||||
$this->assertSame(array(), $form->getExtraData(), 'ChoiceType is compound when expanded, extra data should always be an array');
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
}
|
||||
|
||||
@ -1258,7 +1290,7 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase
|
||||
|
||||
$form->submit('');
|
||||
|
||||
$this->assertNull($form->getData());
|
||||
$this->assertSame('', $form->getData());
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
|
||||
$this->assertTrue($form[0]->getData());
|
||||
|
Reference in New Issue
Block a user