13
13
14
14
use Symfony \Component \Form \AbstractType ;
15
15
use Symfony \Component \Form \ChoiceList \Loader \CallbackChoiceLoader ;
16
+ use Symfony \Component \Form \ChoiceList \Loader \IntlCallbackChoiceLoader ;
16
17
use Symfony \Component \Form \Exception \LogicException ;
17
18
use Symfony \Component \Form \Extension \Core \DataTransformer \DateTimeZoneToStringTransformer ;
18
19
use Symfony \Component \Form \Extension \Core \DataTransformer \IntlTimeZoneToStringTransformer ;
19
20
use Symfony \Component \Form \FormBuilderInterface ;
21
+ use Symfony \Component \Intl \Timezones ;
20
22
use Symfony \Component \OptionsResolver \Options ;
21
23
use Symfony \Component \OptionsResolver \OptionsResolver ;
22
24
@@ -40,19 +42,41 @@ public function buildForm(FormBuilderInterface $builder, array $options)
40
42
public function configureOptions (OptionsResolver $ resolver )
41
43
{
42
44
$ resolver ->setDefaults ([
45
+ 'intl ' => false ,
43
46
'choice_loader ' => function (Options $ options ) {
44
- $ regions = $ options ->offsetGet ('regions ' , false );
45
47
$ input = $ options ['input ' ];
46
48
49
+ if ($ options ['intl ' ]) {
50
+ $ choiceTranslationLocale = $ options ['choice_translation_locale ' ];
51
+
52
+ return new IntlCallbackChoiceLoader (function () use ($ input , $ choiceTranslationLocale ) {
53
+ return self ::getIntlTimezones ($ input , $ choiceTranslationLocale );
54
+ });
55
+ }
56
+
57
+ $ regions = $ options ->offsetGet ('regions ' , false );
58
+
47
59
return new CallbackChoiceLoader (function () use ($ regions , $ input ) {
48
- return self ::getTimezones ($ regions , $ input );
60
+ return self ::getPhpTimezones ($ regions , $ input );
49
61
});
50
62
},
51
63
'choice_translation_domain ' => false ,
64
+ 'choice_translation_locale ' => null ,
52
65
'input ' => 'string ' ,
53
66
'regions ' => \DateTimeZone::ALL ,
54
67
]);
55
68
69
+ $ resolver ->setAllowedTypes ('intl ' , ['bool ' ]);
70
+
71
+ $ resolver ->setAllowedTypes ('choice_translation_locale ' , ['null ' , 'string ' ]);
72
+ $ resolver ->setNormalizer ('choice_translation_locale ' , function (Options $ options , $ value ) {
73
+ if (null !== $ value && !$ options ['intl ' ]) {
74
+ throw new LogicException ('The "choice_translation_locale" option can only be used if the "intl" option is set to true. ' );
75
+ }
76
+
77
+ return $ value ;
78
+ });
79
+
56
80
$ resolver ->setAllowedValues ('input ' , ['string ' , 'datetimezone ' , 'intltimezone ' ]);
57
81
$ resolver ->setNormalizer ('input ' , function (Options $ options , $ value ) {
58
82
if ('intltimezone ' === $ value && !class_exists (\IntlTimeZone::class)) {
@@ -64,6 +88,13 @@ public function configureOptions(OptionsResolver $resolver)
64
88
65
89
$ resolver ->setAllowedTypes ('regions ' , 'int ' );
66
90
$ resolver ->setDeprecated ('regions ' , 'The option "%name%" is deprecated since Symfony 4.2. ' );
91
+ $ resolver ->setNormalizer ('regions ' , function (Options $ options , $ value ) {
92
+ if ($ options ['intl ' ] && \DateTimeZone::ALL !== (\DateTimeZone::ALL & $ value )) {
93
+ throw new LogicException ('The "regions" option can only be used if the "intl" option is set to false. ' );
94
+ }
95
+
96
+ return $ value ;
97
+ });
67
98
}
68
99
69
100
/**
@@ -82,10 +113,7 @@ public function getBlockPrefix()
82
113
return 'timezone ' ;
83
114
}
84
115
85
- /**
86
- * Returns a normalized array of timezone choices.
87
- */
88
- private static function getTimezones (int $ regions , string $ input ): array
116
+ private static function getPhpTimezones (int $ regions , string $ input ): array
89
117
{
90
118
$ timezones = [];
91
119
@@ -99,4 +127,19 @@ private static function getTimezones(int $regions, string $input): array
99
127
100
128
return $ timezones ;
101
129
}
130
+
131
+ private static function getIntlTimezones (string $ input , string $ locale = null ): array
132
+ {
133
+ $ timezones = array_flip (Timezones::getNames ($ locale ));
134
+
135
+ if ('intltimezone ' === $ input ) {
136
+ foreach ($ timezones as $ name => $ timezone ) {
137
+ if ('Etc/Unknown ' === \IntlTimeZone::createTimeZone ($ timezone )->getID ()) {
138
+ unset($ timezones [$ name ]);
139
+ }
140
+ }
141
+ }
142
+
143
+ return $ timezones ;
144
+ }
102
145
}
0 commit comments