Skip to content

Commit 6a9d39c

Browse files
Merge branch '2.8' into 3.4
* 2.8: Command::addOption should allow int in $default [Form] Minor fixes in docs and cs [Form] Fixed empty data for compound date types
2 parents afeb7b8 + 7125437 commit 6a9d39c

File tree

11 files changed

+140
-27
lines changed

11 files changed

+140
-27
lines changed

Extension/Core/Type/DateTimeType.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ public function buildForm(FormBuilderInterface $builder, array $options)
9090
));
9191
}
9292
} else {
93+
// when the form is compound the entries of the array are ignored in favor of children data
94+
// so we need to handle the cascade setting here
95+
$emptyData = $builder->getEmptyData() ?: array();
9396
// Only pass a subset of the options to children
9497
$dateOptions = array_intersect_key($options, array_flip(array(
9598
'years',
@@ -104,6 +107,10 @@ public function buildForm(FormBuilderInterface $builder, array $options)
104107
'invalid_message_parameters',
105108
)));
106109

110+
if (isset($emptyData['date'])) {
111+
$dateOptions['empty_data'] = $emptyData['date'];
112+
}
113+
107114
$timeOptions = array_intersect_key($options, array_flip(array(
108115
'hours',
109116
'minutes',
@@ -119,6 +126,10 @@ public function buildForm(FormBuilderInterface $builder, array $options)
119126
'invalid_message_parameters',
120127
)));
121128

129+
if (isset($emptyData['time'])) {
130+
$timeOptions['empty_data'] = $emptyData['time'];
131+
}
132+
122133
if (false === $options['label']) {
123134
$dateOptions['label'] = false;
124135
$timeOptions['label'] = false;
@@ -224,6 +235,9 @@ public function configureOptions(OptionsResolver $resolver)
224235
// this option.
225236
'data_class' => null,
226237
'compound' => $compound,
238+
'empty_data' => function (Options $options) {
239+
return $options['compound'] ? array() : '';
240+
},
227241
));
228242

229243
// Don't add some defaults in order to preserve the defaults

Extension/Core/Type/DateType.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,21 @@ public function buildForm(FormBuilderInterface $builder, array $options)
7575

7676
$yearOptions = $monthOptions = $dayOptions = array(
7777
'error_bubbling' => true,
78+
'empty_data' => '',
7879
);
80+
// when the form is compound the entries of the array are ignored in favor of children data
81+
// so we need to handle the cascade setting here
82+
$emptyData = $builder->getEmptyData() ?: array();
83+
84+
if (isset($emptyData['year'])) {
85+
$yearOptions['empty_data'] = $emptyData['year'];
86+
}
87+
if (isset($emptyData['month'])) {
88+
$monthOptions['empty_data'] = $emptyData['month'];
89+
}
90+
if (isset($emptyData['day'])) {
91+
$dayOptions['empty_data'] = $emptyData['day'];
92+
}
7993

8094
if (isset($options['invalid_message'])) {
8195
$dayOptions['invalid_message'] = $options['invalid_message'];
@@ -262,6 +276,9 @@ public function configureOptions(OptionsResolver $resolver)
262276
// this option.
263277
'data_class' => null,
264278
'compound' => $compound,
279+
'empty_data' => function (Options $options) {
280+
return $options['compound'] ? array() : '';
281+
},
265282
'choice_translation_domain' => false,
266283
));
267284

Extension/Core/Type/TimeType.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@ public function buildForm(FormBuilderInterface $builder, array $options)
7070
} else {
7171
$hourOptions = $minuteOptions = $secondOptions = array(
7272
'error_bubbling' => true,
73+
'empty_data' => '',
7374
);
75+
// when the form is compound the entries of the array are ignored in favor of children data
76+
// so we need to handle the cascade setting here
77+
$emptyData = $builder->getEmptyData() ?: array();
78+
79+
if (isset($emptyData['hour'])) {
80+
$hourOptions['empty_data'] = $emptyData['hour'];
81+
}
7482

7583
if (isset($options['invalid_message'])) {
7684
$hourOptions['invalid_message'] = $options['invalid_message'];
@@ -135,10 +143,16 @@ public function buildForm(FormBuilderInterface $builder, array $options)
135143
$builder->add('hour', self::$widgets[$options['widget']], $hourOptions);
136144

137145
if ($options['with_minutes']) {
146+
if (isset($emptyData['minute'])) {
147+
$minuteOptions['empty_data'] = $emptyData['minute'];
148+
}
138149
$builder->add('minute', self::$widgets[$options['widget']], $minuteOptions);
139150
}
140151

141152
if ($options['with_seconds']) {
153+
if (isset($emptyData['second'])) {
154+
$secondOptions['empty_data'] = $emptyData['second'];
155+
}
142156
$builder->add('second', self::$widgets[$options['widget']], $secondOptions);
143157
}
144158

@@ -255,6 +269,9 @@ public function configureOptions(OptionsResolver $resolver)
255269
// representation is not \DateTime, but an array, we need to unset
256270
// this option.
257271
'data_class' => null,
272+
'empty_data' => function (Options $options) {
273+
return $options['compound'] ? array() : '';
274+
},
258275
'compound' => $compound,
259276
'choice_translation_domain' => false,
260277
));

Form.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,26 @@
3131
*
3232
* (1) the "model" format required by the form's object
3333
* (2) the "normalized" format for internal processing
34-
* (3) the "view" format used for display
34+
* (3) the "view" format used for display simple fields
35+
* or map children model data for compound fields
3536
*
3637
* A date field, for example, may store a date as "Y-m-d" string (1) in the
3738
* object. To facilitate processing in the field, this value is normalized
3839
* to a DateTime object (2). In the HTML representation of your form, a
39-
* localized string (3) is presented to and modified by the user.
40+
* localized string (3) may be presented to and modified by the user, or it could be an array of values
41+
* to be mapped to choices fields.
4042
*
4143
* In most cases, format (1) and format (2) will be the same. For example,
4244
* a checkbox field uses a Boolean value for both internal processing and
43-
* storage in the object. In these cases you simply need to set a value
45+
* storage in the object. In these cases you simply need to set a view
4446
* transformer to convert between formats (2) and (3). You can do this by
4547
* calling addViewTransformer().
4648
*
4749
* In some cases though it makes sense to make format (1) configurable. To
4850
* demonstrate this, let's extend our above date field to store the value
4951
* either as "Y-m-d" string or as timestamp. Internally we still want to
5052
* use a DateTime object for processing. To convert the data from string/integer
51-
* to DateTime you can set a normalization transformer by calling
53+
* to DateTime you can set a model transformer by calling
5254
* addModelTransformer(). The normalized data is then converted to the displayed
5355
* data as described before.
5456
*
@@ -217,7 +219,7 @@ public function getPropertyPath()
217219
}
218220

219221
if (null === $this->getName() || '' === $this->getName()) {
220-
return;
222+
return null;
221223
}
222224

223225
$parent = $this->parent;
@@ -340,8 +342,8 @@ public function setData($modelData)
340342
$modelData = $event->getData();
341343
}
342344

343-
// Treat data as strings unless a value transformer exists
344-
if (!$this->config->getViewTransformers() && !$this->config->getModelTransformers() && is_scalar($modelData)) {
345+
// Treat data as strings unless a transformer exists
346+
if (is_scalar($modelData) && !$this->config->getViewTransformers() && !$this->config->getModelTransformers()) {
345347
$modelData = (string) $modelData;
346348
}
347349

@@ -1016,7 +1018,7 @@ public function createView(FormView $parent = null)
10161018
}
10171019

10181020
/**
1019-
* Normalizes the value if a normalization transformer is set.
1021+
* Normalizes the value if a model transformer is set.
10201022
*
10211023
* @param mixed $value The value to transform
10221024
*
@@ -1038,7 +1040,7 @@ private function modelToNorm($value)
10381040
}
10391041

10401042
/**
1041-
* Reverse transforms a value if a normalization transformer is set.
1043+
* Reverse transforms a value if a model transformer is set.
10421044
*
10431045
* @param string $value The value to reverse transform
10441046
*
@@ -1062,7 +1064,7 @@ private function normToModel($value)
10621064
}
10631065

10641066
/**
1065-
* Transforms the value if a value transformer is set.
1067+
* Transforms the value if a view transformer is set.
10661068
*
10671069
* @param mixed $value The value to transform
10681070
*
@@ -1093,7 +1095,7 @@ private function normToView($value)
10931095
}
10941096

10951097
/**
1096-
* Reverse transforms a value if a value transformer is set.
1098+
* Reverse transforms a value if a view transformer is set.
10971099
*
10981100
* @param string $value The value to reverse transform
10991101
*

NativeRequestHandler.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use Symfony\Component\Form\Util\ServerParams;
1616

1717
/**
18-
* A request handler using PHP's super globals $_GET, $_POST and $_SERVER.
18+
* A request handler using PHP super globals $_GET, $_POST and $_SERVER.
1919
*
2020
* @author Bernhard Schussek <[email protected]>
2121
*/
@@ -213,7 +213,7 @@ private static function stripEmptyFiles($data)
213213

214214
if (self::$fileKeys === $keys) {
215215
if (UPLOAD_ERR_NO_FILE === $data['error']) {
216-
return;
216+
return null;
217217
}
218218

219219
return $data;

Tests/Extension/Core/Type/DateTimeTypeTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,4 +596,31 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = array(), $expect
596596
$this->assertSame($expectedData, $form->getNormData());
597597
$this->assertSame($expectedData, $form->getData());
598598
}
599+
600+
/**
601+
* @dataProvider provideEmptyData
602+
*/
603+
public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData)
604+
{
605+
$form = $this->factory->create(static::TESTED_TYPE, null, array(
606+
'widget' => $widget,
607+
'empty_data' => $emptyData,
608+
));
609+
$form->submit(null);
610+
611+
$this->assertSame($emptyData, $form->getViewData());
612+
$this->assertEquals($expectedData, $form->getNormData());
613+
$this->assertEquals($expectedData, $form->getData());
614+
}
615+
616+
public function provideEmptyData()
617+
{
618+
$expectedData = \DateTime::createFromFormat('Y-m-d H:i', '2018-11-11 21:23');
619+
620+
return array(
621+
'Simple field' => array('single_text', '2018-11-11T21:23:00', $expectedData),
622+
'Compound text field' => array('text', array('date' => array('year' => '2018', 'month' => '11', 'day' => '11'), 'time' => array('hour' => '21', 'minute' => '23')), $expectedData),
623+
'Compound choice field' => array('choice', array('date' => array('year' => '2018', 'month' => '11', 'day' => '11'), 'time' => array('hour' => '21', 'minute' => '23')), $expectedData),
624+
);
625+
}
599626
}

Tests/Extension/Core/Type/DateTypeTest.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -983,25 +983,36 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = array(), $expect
983983
));
984984
$form->submit(null);
985985

986-
// view transformer write back empty strings in the view data
986+
// view transformer writes back empty strings in the view data
987987
$this->assertSame(array('year' => '', 'month' => '', 'day' => ''), $form->getViewData());
988988
$this->assertSame($expectedData, $form->getNormData());
989989
$this->assertSame($expectedData, $form->getData());
990990
}
991991

992-
public function testSingleTextSubmitNullUsesDefaultEmptyData()
992+
/**
993+
* @dataProvider provideEmptyData
994+
*/
995+
public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData)
993996
{
994-
$emptyData = '2018-11-11';
995997
$form = $this->factory->create(static::TESTED_TYPE, null, array(
996-
'widget' => 'single_text',
998+
'widget' => $widget,
997999
'empty_data' => $emptyData,
9981000
));
9991001
$form->submit(null);
10001002

1001-
$date = new \DateTime($emptyData);
1002-
10031003
$this->assertSame($emptyData, $form->getViewData());
1004-
$this->assertEquals($date, $form->getNormData());
1005-
$this->assertEquals($date, $form->getData());
1004+
$this->assertEquals($expectedData, $form->getNormData());
1005+
$this->assertEquals($expectedData, $form->getData());
1006+
}
1007+
1008+
public function provideEmptyData()
1009+
{
1010+
$expectedData = \DateTime::createFromFormat('Y-m-d H:i:s', '2018-11-11 00:00:00');
1011+
1012+
return array(
1013+
'Simple field' => array('single_text', '2018-11-11', $expectedData),
1014+
'Compound text fields' => array('text', array('year' => '2018', 'month' => '11', 'day' => '11'), $expectedData),
1015+
'Compound choice fields' => array('choice', array('year' => '2018', 'month' => '11', 'day' => '11'), $expectedData),
1016+
);
10061017
}
10071018
}

Tests/Extension/Core/Type/TimeTypeTest.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,9 +776,36 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = array(), $expect
776776
));
777777
$form->submit(null);
778778

779-
// view transformer write back empty strings in the view data
779+
// view transformer writes back empty strings in the view data
780780
$this->assertSame(array('hour' => '', 'minute' => ''), $form->getViewData());
781781
$this->assertSame($expectedData, $form->getNormData());
782782
$this->assertSame($expectedData, $form->getData());
783783
}
784+
785+
/**
786+
* @dataProvider provideEmptyData
787+
*/
788+
public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData)
789+
{
790+
$form = $this->factory->create(static::TESTED_TYPE, null, array(
791+
'widget' => $widget,
792+
'empty_data' => $emptyData,
793+
));
794+
$form->submit(null);
795+
796+
$this->assertSame($emptyData, $form->getViewData());
797+
$this->assertEquals($expectedData, $form->getNormData());
798+
$this->assertEquals($expectedData, $form->getData());
799+
}
800+
801+
public function provideEmptyData()
802+
{
803+
$expectedData = \DateTime::createFromFormat('Y-m-d H:i', '1970-01-01 21:23');
804+
805+
return array(
806+
'Simple field' => array('single_text', '21:23', $expectedData),
807+
'Compound text field' => array('text', array('hour' => '21', 'minute' => '23'), $expectedData),
808+
'Compound choice field' => array('choice', array('hour' => '21', 'minute' => '23'), $expectedData),
809+
);
810+
}
784811
}

Util/FormUtil.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ private function __construct()
2727
* Returns whether the given data is empty.
2828
*
2929
* This logic is reused multiple times throughout the processing of
30-
* a form and needs to be consistent. PHP's keyword `empty` cannot
30+
* a form and needs to be consistent. PHP keyword `empty` cannot
3131
* be used as it also considers 0 and "0" to be empty.
3232
*
3333
* @param mixed $data

Util/OrderedHashMap.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public function offsetSet($key, $value)
128128
$key = array() === $this->orderedKeys
129129
// If the array is empty, use 0 as key
130130
? 0
131-
// Imitate PHP's behavior of generating a key that equals
131+
// Imitate PHP behavior of generating a key that equals
132132
// the highest existing integer key + 1
133133
: 1 + (int) max($this->orderedKeys);
134134
}

Util/OrderedHashMapIterator.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ class OrderedHashMapIterator implements \Iterator
5656
private $current;
5757

5858
/**
59-
* Creates a new iterator.
60-
*
6159
* @param array $elements The elements of the map, indexed by their
6260
* keys
6361
* @param array $orderedKeys The keys of the map in the order in which
@@ -84,7 +82,7 @@ public function __construct(array &$elements, array &$orderedKeys, array &$manag
8482
*/
8583
public function __destruct()
8684
{
87-
// Use array_splice() instead of isset() to prevent holes in the
85+
// Use array_splice() instead of unset() to prevent holes in the
8886
// array indices, which would break the initialization of $cursorId
8987
array_splice($this->managedCursors, $this->cursorId, 1);
9088
}

0 commit comments

Comments
 (0)