Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit7294b59

Browse files
committed
[Validator] Allow intl timezones
1 parent1c110fa commit7294b59

File tree

3 files changed

+99
-13
lines changed

3 files changed

+99
-13
lines changed

‎src/Symfony/Component/Validator/Constraints/Timezone.php‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,18 @@ class Timezone extends Constraint
2626
publicconstTIMEZONE_IDENTIFIER_ERROR ='5ce113e6-5e64-4ea2-90fe-d2233956db13';
2727
publicconstTIMEZONE_IDENTIFIER_IN_ZONE_ERROR ='b57767b1-36c0-40ac-a3d7-629420c775b8';
2828
publicconstTIMEZONE_IDENTIFIER_IN_COUNTRY_ERROR ='c4a22222-dc92-4fc0-abb0-d95b268c7d0b';
29+
publicconstTIMEZONE_IDENTIFIER_INTL_ERROR ='45863c26-88dc-41ba-bf53-c73bd1f7e90d';
2930

3031
public$zone = \DateTimeZone::ALL;
3132
public$countryCode;
33+
public$intlCompatible =false;
3234
public$message ='This value is not a valid timezone.';
3335

3436
protectedstatic$errorNames = [
3537
self::TIMEZONE_IDENTIFIER_ERROR =>'TIMEZONE_IDENTIFIER_ERROR',
3638
self::TIMEZONE_IDENTIFIER_IN_ZONE_ERROR =>'TIMEZONE_IDENTIFIER_IN_ZONE_ERROR',
3739
self::TIMEZONE_IDENTIFIER_IN_COUNTRY_ERROR =>'TIMEZONE_IDENTIFIER_IN_COUNTRY_ERROR',
40+
self::TIMEZONE_IDENTIFIER_INTL_ERROR =>'TIMEZONE_IDENTIFIER_INTL_ERROR',
3841
];
3942

4043
/**
@@ -51,5 +54,8 @@ public function __construct(array $options = null)
5154
}elseif (\DateTimeZone::PER_COUNTRY !== (\DateTimeZone::PER_COUNTRY &$this->zone)) {
5255
thrownewConstraintDefinitionException('The option "countryCode" can only be used when the "zone" option is configured with "\DateTimeZone::PER_COUNTRY".');
5356
}
57+
if ($this->intlCompatible && !class_exists(\IntlTimeZone::class)) {
58+
thrownewConstraintDefinitionException('The option "intlCompatible" can only be used when the PHP intl extension is available.');
59+
}
5460
}
5561
}

‎src/Symfony/Component/Validator/Constraints/TimezoneValidator.php‎

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespaceSymfony\Component\Validator\Constraints;
1313

14+
useSymfony\Component\Intl\Exception\MissingResourceException;
15+
useSymfony\Component\Intl\Timezones;
1416
useSymfony\Component\Validator\Constraint;
1517
useSymfony\Component\Validator\ConstraintValidator;
1618
useSymfony\Component\Validator\Exception\UnexpectedTypeException;
@@ -43,14 +45,28 @@ public function validate($value, Constraint $constraint)
4345

4446
$value = (string)$value;
4547

46-
// @see: https://bugs.php.net/bug.php?id=75928
48+
if ($constraint->intlCompatible &&'Etc/Unknown' === \IntlTimeZone::createTimeZone($value)->getID()) {
49+
$this->context->buildViolation($constraint->message)
50+
->setParameter('{{ value }}',$this->formatValue($value))
51+
->setCode(Timezone::TIMEZONE_IDENTIFIER_INTL_ERROR)
52+
->addViolation();
53+
54+
return;
55+
}
56+
4757
if ($constraint->countryCode) {
48-
$timezoneIds = @\DateTimeZone::listIdentifiers($constraint->zone,$constraint->countryCode) ?: [];
58+
$phpTimezoneIds = @\DateTimeZone::listIdentifiers($constraint->zone,$constraint->countryCode) ?: [];
59+
try {
60+
$intlTimezoneIds = Timezones::forCountryCode($constraint->countryCode);
61+
}catch (MissingResourceException$e) {
62+
$intlTimezoneIds = [];
63+
}
4964
}else {
50-
$timezoneIds = \DateTimeZone::listIdentifiers($constraint->zone);
65+
$phpTimezoneIds = \DateTimeZone::listIdentifiers($constraint->zone);
66+
$intlTimezoneIds =self::getIntlTimezones($constraint->zone);
5167
}
5268

53-
if (\in_array($value,$timezoneIds,true)) {
69+
if (\in_array($value,$phpTimezoneIds,true) ||\in_array($value,$intlTimezoneIds,true)) {
5470
return;
5571
}
5672

@@ -63,9 +79,9 @@ public function validate($value, Constraint $constraint)
6379
}
6480

6581
$this->context->buildViolation($constraint->message)
66-
->setParameter('{{ value }}',$this->formatValue($value))
67-
->setCode($code)
68-
->addViolation();
82+
->setParameter('{{ value }}',$this->formatValue($value))
83+
->setCode($code)
84+
->addViolation();
6985
}
7086

7187
/**
@@ -89,4 +105,26 @@ protected function formatValue($value, $format = 0)
89105

90106
returnarray_search($value, (new \ReflectionClass(\DateTimeZone::class))->getConstants(),true) ?:$value;
91107
}
108+
109+
privatestaticfunctiongetIntlTimezones(int$zone):array
110+
{
111+
$timezones = Timezones::getIds();
112+
113+
if (\DateTimeZone::ALL === (\DateTimeZone::ALL &$zone)) {
114+
return$timezones;
115+
}
116+
117+
$filtered = [];
118+
foreach ((new \ReflectionClass(\DateTimeZone::class))->getConstants()as$const =>$flag) {
119+
if ($flag !== ($flag &$zone)) {
120+
continue;
121+
}
122+
123+
$filtered[] =array_filter($timezones,staticfunction ($id)use ($const) {
124+
return0 ===stripos($id,$const.'/');
125+
});
126+
}
127+
128+
return$filtered ?array_merge(...$filtered) : [];
129+
}
92130
}

‎src/Symfony/Component/Validator/Tests/Constraints/TimezoneValidatorTest.php‎

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,26 @@ public function testValidTimezones(string $timezone)
6060

6161
publicfunctiongetValidTimezones():iterable
6262
{
63+
// ICU standard (alias/BC in PHP)
64+
yield ['Etc/UTC'];
65+
yield ['Etc/GMT'];
66+
yield ['America/Buenos_Aires'];
67+
68+
// PHP standard (alias in ICU)
69+
yield ['UTC'];
6370
yield ['America/Argentina/Buenos_Aires'];
71+
72+
// not deprecated in ICU
73+
yield ['CST6CDT'];
74+
yield ['EST5EDT'];
75+
yield ['MST7MDT'];
76+
yield ['PST8PDT'];
77+
yield ['America/Montreal'];
78+
79+
// expired in ICU
80+
yield ['Europe/Saratov'];
81+
82+
// standard
6483
yield ['America/Barbados'];
6584
yield ['America/Toronto'];
6685
yield ['Antarctica/Syowa'];
@@ -71,7 +90,6 @@ public function getValidTimezones(): iterable
7190
yield ['Europe/Copenhagen'];
7291
yield ['Europe/Paris'];
7392
yield ['Pacific/Noumea'];
74-
yield ['UTC'];
7593
}
7694

7795
/**
@@ -90,6 +108,8 @@ public function testValidGroupedTimezones(string $timezone, int $zone)
90108

91109
publicfunctiongetValidGroupedTimezones():iterable
92110
{
111+
yield ['America/Buenos_Aires', \DateTimeZone::AMERICA | \DateTimeZone::AUSTRALIA];// icu
112+
yield ['America/Argentina/Buenos_Aires', \DateTimeZone::AMERICA];// php
93113
yield ['America/Argentina/Cordoba', \DateTimeZone::AMERICA];
94114
yield ['America/Barbados', \DateTimeZone::AMERICA];
95115
yield ['Africa/Cairo', \DateTimeZone::AFRICA];
@@ -124,6 +144,7 @@ public function testInvalidTimezoneWithoutZone(string $timezone)
124144

125145
publicfunctiongetInvalidTimezones():iterable
126146
{
147+
yield ['Buenos_Aires/America'];
127148
yield ['Buenos_Aires/Argentina/America'];
128149
yield ['Mayotte/Indian'];
129150
yield ['foobar'];
@@ -149,11 +170,15 @@ public function testInvalidGroupedTimezones(string $timezone, int $zone)
149170

150171
publicfunctiongetInvalidGroupedTimezones():iterable
151172
{
173+
yield ['America/Buenos_Aires', \DateTimeZone::ASIA | \DateTimeZone::AUSTRALIA];// icu
174+
yield ['America/Argentina/Buenos_Aires', \DateTimeZone::EUROPE];// php
152175
yield ['Antarctica/McMurdo', \DateTimeZone::AMERICA];
153176
yield ['America/Barbados', \DateTimeZone::ANTARCTICA];
154177
yield ['Europe/Kiev', \DateTimeZone::ARCTIC];
155178
yield ['Asia/Ho_Chi_Minh', \DateTimeZone::INDIAN];
156179
yield ['Asia/Ho_Chi_Minh', \DateTimeZone::INDIAN | \DateTimeZone::ANTARCTICA];
180+
yield ['UTC', \DateTimeZone::EUROPE];
181+
yield ['Etc/UTC', \DateTimeZone::EUROPE];
157182
}
158183

159184
/**
@@ -173,6 +198,8 @@ public function testValidGroupedTimezonesByCountry(string $timezone, string $cou
173198

174199
publicfunctiongetValidGroupedTimezonesByCountry():iterable
175200
{
201+
yield ['America/Buenos_Aires','AR'];// icu
202+
yield ['America/Argentina/Buenos_Aires','AR'];// php
176203
yield ['America/Argentina/Cordoba','AR'];
177204
yield ['America/Barbados','BB'];
178205
yield ['Africa/Cairo','EG'];
@@ -215,6 +242,7 @@ public function getInvalidGroupedTimezonesByCountry(): iterable
215242
yield ['America/Argentina/Cordoba','FR'];
216243
yield ['America/Barbados','PT'];
217244
yield ['Europe/Bern','FR'];
245+
yield ['Etc/UTC','NL'];
218246
yield ['Europe/Amsterdam','AC'];// "AC" has no timezones, but is a valid country code
219247
}
220248

@@ -267,8 +295,6 @@ public function testDeprecatedTimezonesAreInvalidWithoutBC(string $timezone)
267295

268296
publicfunctiongetDeprecatedTimezones():iterable
269297
{
270-
yield ['America/Buenos_Aires'];
271-
yield ['America/Montreal'];
272298
yield ['Australia/ACT'];
273299
yield ['Australia/LHI'];
274300
yield ['Australia/Queensland'];
@@ -277,13 +303,29 @@ public function getDeprecatedTimezones(): iterable
277303
yield ['Canada/Mountain'];
278304
yield ['Canada/Pacific'];
279305
yield ['CET'];
280-
yield ['CST6CDT'];
281-
yield ['Etc/GMT'];
306+
yield ['GMT'];
282307
yield ['Etc/Greenwich'];
283308
yield ['Etc/UCT'];
284309
yield ['Etc/Universal'];
285-
yield ['Etc/UTC'];
286310
yield ['Etc/Zulu'];
287311
yield ['US/Pacific'];
288312
}
313+
314+
/**
315+
* @requires extension intl
316+
*/
317+
publicfunctiontestIntlCompatibility()
318+
{
319+
$constraint =newTimezone([
320+
'message' =>'myMessage',
321+
'intlCompatible' =>true,
322+
]);
323+
324+
$this->validator->validate('Europe/Saratov',$constraint);
325+
326+
$this->buildViolation('myMessage')
327+
->setParameter('{{ value }}','"Europe/Saratov"')
328+
->setCode(Timezone::TIMEZONE_IDENTIFIER_INTL_ERROR)
329+
->assertRaised();
330+
}
289331
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp