Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 02b1768

Browse files
committed
[Form] Add option widget to ChoiceType
1 parent 729b98c commit 02b1768

File tree

5 files changed

+265
-6
lines changed

5 files changed

+265
-6
lines changed

src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@
3535
{%- endblock textarea_widget -%}
3636

3737
{%- block choice_widget -%}
38-
{% if expanded %}
38+
{% if 'hidden' == widget %}
39+
{{- block('hidden_widget') -}}
40+
{% elseif 'text' == widget %}
41+
{{- block('form_widget_simple') -}}
42+
{% elseif expanded %}
3943
{{- block('choice_widget_expanded') -}}
4044
{% else %}
4145
{{- block('choice_widget_collapsed') -}}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Extension\Core\DataTransformer;
13+
14+
use Symfony\Component\Form\DataTransformerInterface;
15+
use Symfony\Component\Form\Exception\TransformationFailedException;
16+
17+
/**
18+
* Converts an array of values to a string with multiple values separated by a delimiter.
19+
*
20+
* @author Bilal Amarni <[email protected]>
21+
*/
22+
class ValuesToStringTransformer implements DataTransformerInterface
23+
{
24+
/**
25+
* @var string
26+
*/
27+
private $delimiter;
28+
29+
/**
30+
* @var bool
31+
*/
32+
private $trim;
33+
34+
/**
35+
* @param string $delimiter
36+
* @param bool $trim
37+
*/
38+
public function __construct($delimiter, $trim)
39+
{
40+
$this->delimiter = $delimiter;
41+
$this->trim = $trim;
42+
}
43+
44+
/**
45+
* @param array $array
46+
*
47+
* @return string
48+
*
49+
* @throws UnexpectedTypeException if the given value is not an array
50+
*/
51+
public function transform($array)
52+
{
53+
if (null === $array) {
54+
return '';
55+
}
56+
57+
if (!is_array($array)) {
58+
throw new TransformationFailedException('Expected an array');
59+
}
60+
61+
return implode($this->delimiter, $array);
62+
}
63+
64+
/**
65+
* @param string $string
66+
*
67+
* @return array
68+
*
69+
* @throws UnexpectedTypeException if the given value is not a string
70+
*/
71+
public function reverseTransform($string)
72+
{
73+
if (empty($string)) {
74+
return array();
75+
}
76+
77+
if (!is_string($string)) {
78+
throw new TransformationFailedException('Expected a string');
79+
}
80+
81+
$values = explode($this->delimiter, $string);
82+
83+
if ($this->trim) {
84+
$values = array_map('trim', $values);
85+
}
86+
87+
return $values;
88+
}
89+
}

src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener;
3333
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoiceToValueTransformer;
3434
use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer;
35+
use Symfony\Component\Form\Extension\Core\DataTransformer\ValuesToStringTransformer;
3536
use Symfony\Component\OptionsResolver\Options;
3637
use Symfony\Component\OptionsResolver\OptionsResolver;
3738

@@ -54,7 +55,7 @@ public function __construct(ChoiceListFactoryInterface $choiceListFactory = null
5455
*/
5556
public function buildForm(FormBuilderInterface $builder, array $options)
5657
{
57-
if ($options['expanded']) {
58+
if ($options['expanded'] && !in_array($options['widget'], array('text', 'hidden'))) {
5859
$builder->setDataMapper($options['multiple']
5960
? new CheckboxListMapper($options['choice_list'])
6061
: new RadioListMapper($options['choice_list']));
@@ -140,10 +141,15 @@ public function buildForm(FormBuilderInterface $builder, array $options)
140141
});
141142
}
142143
} elseif ($options['multiple']) {
143-
// <select> tag with "multiple" option
144+
// "select", "text" or "hidden" widget with "multiple" option
144145
$builder->addViewTransformer(new ChoicesToValuesTransformer($options['choice_list']));
146+
147+
// for "text" / "hidden" widget, view data uses a delimiter
148+
if (in_array($options['widget'], array('text', 'hidden'))) {
149+
$builder->addViewTransformer(new ValuesToStringTransformer($options['delimiter'], $options['trim']));
150+
}
145151
} else {
146-
// <select> tag without "multiple" option
152+
// "select", "text" or "hidden" tag without "multiple" option
147153
$builder->addViewTransformer(new ChoiceToValueTransformer($options['choice_list']));
148154
}
149155

@@ -170,15 +176,20 @@ public function buildView(FormView $view, FormInterface $form, array $options)
170176
: $this->createChoiceListView($options['choice_list'], $options);
171177

172178
$view->vars = array_replace($view->vars, array(
179+
'widget' => $options['widget'],
173180
'multiple' => $options['multiple'],
174-
'expanded' => $options['expanded'],
181+
'expanded' => $options['expanded'], // BC
175182
'preferred_choices' => $choiceListView->preferredChoices,
176183
'choices' => $choiceListView->choices,
177184
'separator' => '-------------------',
178185
'placeholder' => null,
179186
'choice_translation_domain' => $choiceTranslationDomain,
180187
));
181188

189+
if (in_array($options['widget'], array('text', 'hidden'))) {
190+
return;
191+
}
192+
182193
// The decision, whether a choice is selected, is potentially done
183194
// thousand of times during the rendering of a template. Provide a
184195
// closure here that is optimized for the value of the form, to
@@ -218,6 +229,10 @@ public function buildView(FormView $view, FormInterface $form, array $options)
218229
*/
219230
public function finishView(FormView $view, FormInterface $form, array $options)
220231
{
232+
if (in_array($options['widget'], array('text', 'hidden'))) {
233+
return;
234+
}
235+
221236
if ($options['expanded']) {
222237
// Radio buttons should have the same name as the parent
223238
$childName = $view->vars['full_name'];
@@ -292,6 +307,18 @@ public function configureOptions(OptionsResolver $resolver)
292307
return;
293308
};
294309

310+
$multipleNormalizer = function (Options $options, $multiple) {
311+
if (in_array($options['widget'], array('radio', 'checkbox'))) {
312+
return 'checkbox' == $options['widget'];
313+
}
314+
315+
return $multiple;
316+
};
317+
318+
$expandedNomalizer = function (Options $options, $expanded) {
319+
return in_array($options['widget'], array('radio', 'checkbox')) ?: $expanded;
320+
};
321+
295322
$choiceListNormalizer = function (Options $options, $choiceList) use ($choiceListFactory) {
296323
if ($choiceList) {
297324
@trigger_error('The "choice_list" option is deprecated since version 2.7 and will be removed in 3.0. Use "choice_loader" instead.', E_USER_DEPRECATED);
@@ -364,8 +391,10 @@ public function configureOptions(OptionsResolver $resolver)
364391
};
365392

366393
$resolver->setDefaults(array(
394+
'widget' => null,
367395
'multiple' => false,
368-
'expanded' => false,
396+
'delimiter' => ',',
397+
'expanded' => false, // deprecated
369398
'choice_list' => null, // deprecated
370399
'choices' => array(),
371400
'choices_as_values' => false,
@@ -388,6 +417,8 @@ public function configureOptions(OptionsResolver $resolver)
388417
'choice_translation_domain' => true,
389418
));
390419

420+
$resolver->setNormalizer('expanded', $expandedNomalizer);
421+
$resolver->setNormalizer('multiple', $multipleNormalizer);
391422
$resolver->setNormalizer('choices', $choicesNormalizer);
392423
$resolver->setNormalizer('choice_list', $choiceListNormalizer);
393424
$resolver->setNormalizer('placeholder', $placeholderNormalizer);
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
13+
14+
use Symfony\Component\Form\Extension\Core\DataTransformer\ValuesToStringTransformer;
15+
16+
class ValuesToStringTransformerTest extends \PHPUnit_Framework_TestCase
17+
{
18+
private $transformer;
19+
20+
protected function setUp()
21+
{
22+
$this->transformer = new ValuesToStringTransformer(',', true);
23+
}
24+
25+
protected function tearDown()
26+
{
27+
$this->transformer = null;
28+
}
29+
30+
public function testTransform()
31+
{
32+
$output = 'a,b,c';
33+
34+
$this->assertSame($output, $this->transformer->transform(array('a', 'b', 'c')));
35+
}
36+
37+
public function testTransformNull()
38+
{
39+
$this->assertSame('', $this->transformer->transform(null));
40+
}
41+
42+
/**
43+
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
44+
*/
45+
public function testReverseTransformRequiresAnArray()
46+
{
47+
$this->transformer->transform('a, b, c');
48+
}
49+
50+
public function testReverseTransform()
51+
{
52+
$input = 'a, b ,c ';
53+
54+
$this->assertSame(array('a', 'b', 'c'), $this->transformer->reverseTransform($input));
55+
}
56+
57+
public function testReverseTransformEmpty()
58+
{
59+
$input = '';
60+
61+
$this->assertSame(array(), $this->transformer->reverseTransform($input));
62+
}
63+
64+
/**
65+
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
66+
*/
67+
public function testReverseTransformRequiresAString()
68+
{
69+
$this->transformer->reverseTransform(array('a', 'b', 'c'));
70+
}
71+
}

src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,4 +1887,68 @@ public function testInitializeWithDefaultObjectChoice()
18871887
// Trigger data initialization
18881888
$form->getViewData();
18891889
}
1890+
1891+
/**
1892+
* @dataProvider simpleWidgetsProvider
1893+
*/
1894+
public function testSubmitChoicesWithSimpleWidgets($widget)
1895+
{
1896+
$form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array(
1897+
'widget' => $widget,
1898+
'multiple' => false,
1899+
'choices' => $this->choices,
1900+
'choices_as_values' => true,
1901+
));
1902+
1903+
$form->submit('b');
1904+
1905+
$this->assertEquals('b', $form->getData());
1906+
$this->assertEquals('b', $form->getViewData());
1907+
}
1908+
1909+
/**
1910+
* @dataProvider simpleWidgetsProvider
1911+
*/
1912+
public function testSubmitMultipleChoicesWithSimpleWidgets($widget)
1913+
{
1914+
$form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array(
1915+
'widget' => $widget,
1916+
'multiple' => true,
1917+
'choices' => $this->choices,
1918+
'choices_as_values' => true,
1919+
));
1920+
1921+
$form->submit('a,b');
1922+
1923+
$this->assertEquals(array('a', 'b'), $form->getData());
1924+
$this->assertEquals('a,b', $form->getViewData());
1925+
}
1926+
1927+
/**
1928+
* @dataProvider simpleWidgetsProvider
1929+
*/
1930+
public function testSubmitMultipleChoicesDelimiterAndTrimWithSimpleWidgets($widget)
1931+
{
1932+
$form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array(
1933+
'widget' => $widget,
1934+
'multiple' => true,
1935+
'delimiter' => '|',
1936+
'trim' => true,
1937+
'choices' => $this->choices,
1938+
'choices_as_values' => true,
1939+
));
1940+
1941+
$form->submit('a| b ');
1942+
1943+
$this->assertEquals(array('a', 'b'), $form->getData());
1944+
$this->assertEquals('a|b', $form->getViewData());
1945+
}
1946+
1947+
public function simpleWidgetsProvider()
1948+
{
1949+
return array(
1950+
array('text'),
1951+
array('hidden'),
1952+
);
1953+
}
18901954
}

0 commit comments

Comments
 (0)