Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9208244

Browse filesBrowse files
committed
feature #23648 [Form] Add input + regions options to TimezoneType (ro0NL)
This PR was merged into the 3.4 branch. Discussion ---------- [Form] Add input + regions options to TimezoneType | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | #... <!-- #-prefixed issue number(s), if any --> | License | MIT | Doc PR | symfony/symfony-docs#8223 I want to use `\DateTimeZone` as a model format, with only european timezones in the form available. Hence the new options. Commits ------- 183307b [Form] Add input + regions options to TimezoneType
2 parents 40a3466 + 183307b commit 9208244
Copy full SHA for 9208244

File tree

7 files changed

+272
-5
lines changed
Filter options

7 files changed

+272
-5
lines changed

‎UPGRADE-3.4.md

Copy file name to clipboardExpand all lines: UPGRADE-3.4.md
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,38 @@ Finder
7474
deprecated and will be removed in 4.0 as it used to fix a bug which existed
7575
before version 5.5.23/5.6.7.
7676

77+
Form
78+
----
79+
80+
* Deprecated `ChoiceLoaderInterface` implementation in `TimezoneType`. Use the "choice_loader" option instead.
81+
82+
Before:
83+
```php
84+
class MyTimezoneType extends TimezoneType
85+
{
86+
public function loadChoices()
87+
{
88+
// override the method
89+
}
90+
}
91+
```
92+
93+
After:
94+
```php
95+
class MyTimezoneType extends AbstractType
96+
{
97+
public function. getParent()
98+
{
99+
return TimezoneType::class;
100+
}
101+
102+
public function configureOptions(OptionsResolver $resolver)
103+
{
104+
$resolver->setDefault('choice_loader', ...); // override the option instead
105+
}
106+
}
107+
```
108+
77109
FrameworkBundle
78110
---------------
79111

‎UPGRADE-4.0.md

Copy file name to clipboardExpand all lines: UPGRADE-4.0.md
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,35 @@ Form
282282
));
283283
```
284284

285+
* Removed `ChoiceLoaderInterface` implementation in `TimezoneType`. Use the "choice_loader" option instead.
286+
287+
Before:
288+
```php
289+
class MyTimezoneType extends TimezoneType
290+
{
291+
public function loadChoices()
292+
{
293+
// override the method
294+
}
295+
}
296+
```
297+
298+
After:
299+
```php
300+
class MyTimezoneType extends AbstractType
301+
{
302+
public function. getParent()
303+
{
304+
return TimezoneType::class;
305+
}
306+
307+
public function configureOptions(OptionsResolver $resolver)
308+
{
309+
$resolver->setDefault('choice_loader', ...); // override the option instead
310+
}
311+
}
312+
```
313+
285314
FrameworkBundle
286315
---------------
287316

‎src/Symfony/Component/Form/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ CHANGELOG
55
-----
66

77
* added `DebugCommand`
8+
* deprecated `ChoiceLoaderInterface` implementation in `TimezoneType`
9+
* added options "input" and "regions" to `TimezoneType`
810

911
3.3.0
1012
-----
+82Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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+
* Transforms between a timezone identifier string and a DateTimeZone object.
19+
*
20+
* @author Roland Franssen <franssen.roland@gmai.com>
21+
*/
22+
class DateTimeZoneToStringTransformer implements DataTransformerInterface
23+
{
24+
private $multiple;
25+
26+
public function __construct($multiple = false)
27+
{
28+
$this->multiple = $multiple;
29+
}
30+
31+
/**
32+
* {@inheritdoc}
33+
*/
34+
public function transform($dateTimeZone)
35+
{
36+
if (null === $dateTimeZone) {
37+
return;
38+
}
39+
40+
if ($this->multiple) {
41+
if (!is_array($dateTimeZone)) {
42+
throw new TransformationFailedException('Expected an array.');
43+
}
44+
45+
return array_map(array(new self(), 'transform'), $dateTimeZone);
46+
}
47+
48+
if (!$dateTimeZone instanceof \DateTimeZone) {
49+
throw new TransformationFailedException('Expected a \DateTimeZone.');
50+
}
51+
52+
return $dateTimeZone->getName();
53+
}
54+
55+
/**
56+
* {@inheritdoc}
57+
*/
58+
public function reverseTransform($value)
59+
{
60+
if (null === $value) {
61+
return;
62+
}
63+
64+
if ($this->multiple) {
65+
if (!is_array($value)) {
66+
throw new TransformationFailedException('Expected an array.');
67+
}
68+
69+
return array_map(array(new self(), 'reverseTransform'), $value);
70+
}
71+
72+
if (!is_string($value)) {
73+
throw new TransformationFailedException('Expected a string.');
74+
}
75+
76+
try {
77+
return new \DateTimeZone($value);
78+
} catch (\Exception $e) {
79+
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
80+
}
81+
}
82+
}

‎src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php
+44-5Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313

1414
use Symfony\Component\Form\AbstractType;
1515
use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
16+
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
1617
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
18+
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeZoneToStringTransformer;
19+
use Symfony\Component\Form\FormBuilderInterface;
1720
use Symfony\Component\OptionsResolver\Options;
1821
use Symfony\Component\OptionsResolver\OptionsResolver;
1922

@@ -25,9 +28,21 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface
2528
* The choices are generated from the ICU function \DateTimeZone::listIdentifiers().
2629
*
2730
* @var ArrayChoiceList
31+
*
32+
* @deprecated since version 3.4, to be removed in 4.0
2833
*/
2934
private $choiceList;
3035

36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function buildForm(FormBuilderInterface $builder, array $options)
40+
{
41+
if ('datetimezone' === $options['input']) {
42+
$builder->addModelTransformer(new DateTimeZoneToStringTransformer($options['multiple']));
43+
}
44+
}
45+
3146
/**
3247
* {@inheritdoc}
3348
*/
@@ -41,10 +56,20 @@ public function configureOptions(OptionsResolver $resolver)
4156
return null;
4257
}
4358

44-
return $this;
59+
$regions = $options['regions'];
60+
61+
return new CallbackChoiceLoader(function () use ($regions) {
62+
return self::getTimezones($regions);
63+
});
4564
},
4665
'choice_translation_domain' => false,
66+
'input' => 'string',
67+
'regions' => \DateTimeZone::ALL,
4768
));
69+
70+
$resolver->setAllowedValues('input', array('string', 'datetimezone'));
71+
72+
$resolver->setAllowedTypes('regions', 'int');
4873
}
4974

5075
/**
@@ -65,21 +90,29 @@ public function getBlockPrefix()
6590

6691
/**
6792
* {@inheritdoc}
93+
*
94+
* @deprecated since version 3.4, to be removed in 4.0
6895
*/
6996
public function loadChoiceList($value = null)
7097
{
98+
@trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
99+
71100
if (null !== $this->choiceList) {
72101
return $this->choiceList;
73102
}
74103

75-
return $this->choiceList = new ArrayChoiceList(self::getTimezones(), $value);
104+
return $this->choiceList = new ArrayChoiceList(self::getTimezones(\DateTimeZone::ALL), $value);
76105
}
77106

78107
/**
79108
* {@inheritdoc}
109+
*
110+
* @deprecated since version 3.4, to be removed in 4.0
80111
*/
81112
public function loadChoicesForValues(array $values, $value = null)
82113
{
114+
@trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
115+
83116
// Optimize
84117
$values = array_filter($values);
85118
if (empty($values)) {
@@ -96,9 +129,13 @@ public function loadChoicesForValues(array $values, $value = null)
96129

97130
/**
98131
* {@inheritdoc}
132+
*
133+
* @deprecated since version 3.4, to be removed in 4.0
99134
*/
100135
public function loadValuesForChoices(array $choices, $value = null)
101136
{
137+
@trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
138+
102139
// Optimize
103140
$choices = array_filter($choices);
104141
if (empty($choices)) {
@@ -116,13 +153,15 @@ public function loadValuesForChoices(array $choices, $value = null)
116153
/**
117154
* Returns a normalized array of timezone choices.
118155
*
156+
* @param int $regions
157+
*
119158
* @return array The timezone choices
120159
*/
121-
private static function getTimezones()
160+
private static function getTimezones($regions)
122161
{
123162
$timezones = array();
124163

125-
foreach (\DateTimeZone::listIdentifiers() as $timezone) {
164+
foreach (\DateTimeZone::listIdentifiers($regions) as $timezone) {
126165
$parts = explode('/', $timezone);
127166

128167
if (count($parts) > 2) {
@@ -139,6 +178,6 @@ private static function getTimezones()
139178
$timezones[$region][str_replace('_', ' ', $name)] = $timezone;
140179
}
141180

142-
return $timezones;
181+
return 1 === count($timezones) ? reset($timezones) : $timezones;
143182
}
144183
}
+56Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\DateTimeZoneToStringTransformer;
15+
use PHPUnit\Framework\TestCase;
16+
17+
class DateTimeZoneToStringTransformerTest extends TestCase
18+
{
19+
public function testSingle()
20+
{
21+
$transformer = new DateTimeZoneToStringTransformer();
22+
23+
$this->assertNull($transformer->transform(null));
24+
$this->assertNull($transformer->reverseTransform(null));
25+
26+
$this->assertSame('Europe/Amsterdam', $transformer->transform(new \DateTimeZone('Europe/Amsterdam')));
27+
$this->assertEquals(new \DateTimeZone('Europe/Amsterdam'), $transformer->reverseTransform('Europe/Amsterdam'));
28+
}
29+
30+
public function testMultiple()
31+
{
32+
$transformer = new DateTimeZoneToStringTransformer(true);
33+
34+
$this->assertNull($transformer->transform(null));
35+
$this->assertNull($transformer->reverseTransform(null));
36+
37+
$this->assertSame(array('Europe/Amsterdam'), $transformer->transform(array(new \DateTimeZone('Europe/Amsterdam'))));
38+
$this->assertEquals(array(new \DateTimeZone('Europe/Amsterdam')), $transformer->reverseTransform(array('Europe/Amsterdam')));
39+
}
40+
41+
/**
42+
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
43+
*/
44+
public function testInvalidTimezone()
45+
{
46+
(new DateTimeZoneToStringTransformer())->transform(1);
47+
}
48+
49+
/**
50+
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
51+
*/
52+
public function testUnknownTimezone()
53+
{
54+
(new DateTimeZoneToStringTransformer(true))->reverseTransform(array('Foo/Bar'));
55+
}
56+
}

‎src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php
+27Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,31 @@ public function testSubmitNull($expected = null, $norm = null, $view = null)
3333
{
3434
parent::testSubmitNull($expected, $norm, '');
3535
}
36+
37+
public function testDateTimeZoneInput()
38+
{
39+
$form = $this->factory->create(static::TESTED_TYPE, new \DateTimeZone('America/New_York'), array('input' => 'datetimezone'));
40+
41+
$this->assertSame('America/New_York', $form->createView()->vars['value']);
42+
43+
$form->submit('Europe/Amsterdam');
44+
45+
$this->assertEquals(new \DateTimeZone('Europe/Amsterdam'), $form->getData());
46+
47+
$form = $this->factory->create(static::TESTED_TYPE, array(new \DateTimeZone('America/New_York')), array('input' => 'datetimezone', 'multiple' => true));
48+
49+
$this->assertSame(array('America/New_York'), $form->createView()->vars['value']);
50+
51+
$form->submit(array('Europe/Amsterdam', 'Europe/Paris'));
52+
53+
$this->assertEquals(array(new \DateTimeZone('Europe/Amsterdam'), new \DateTimeZone('Europe/Paris')), $form->getData());
54+
}
55+
56+
public function testFilterByRegions()
57+
{
58+
$choices = $this->factory->create(static::TESTED_TYPE, null, array('regions' => \DateTimeZone::EUROPE))
59+
->createView()->vars['choices'];
60+
61+
$this->assertContains(new ChoiceView('Europe/Amsterdam', 'Europe/Amsterdam', 'Amsterdam'), $choices, '', false, false);
62+
}
3663
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.