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 f87bf3b

Browse filesBrowse files
phansyshhamon
authored andcommitted
Add new TimezoneValidator
1 parent f527acf commit f87bf3b
Copy full SHA for f87bf3b

File tree

7 files changed

+491
-0
lines changed
Filter options

7 files changed

+491
-0
lines changed
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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\Validator\Constraints;
13+
14+
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
16+
17+
/**
18+
* @Annotation
19+
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
20+
*
21+
* @author Javier Spagnoletti <phansys@gmail.com>
22+
* @author Hugo Hamon <hugohamon@neuf.fr>
23+
*/
24+
class Timezone extends Constraint
25+
{
26+
public const NO_SUCH_TIMEZONE_IDENTIFIER_ERROR = '5ce113e6-5e64-4ea2-90fe-d2233956db13';
27+
public const NO_SUCH_TIMEZONE_IDENTIFIER_IN_ZONE_ERROR = 'b57767b1-36c0-40ac-a3d7-629420c775b8';
28+
public const NO_SUCH_TIMEZONE_IDENTIFIER_IN_COUNTRY_ERROR = 'c4a22222-dc92-4fc0-abb0-d95b268c7d0b';
29+
30+
public $zone = \DateTimeZone::ALL;
31+
public $countryCode;
32+
public $message = 'This value is not a valid timezone.';
33+
34+
protected static $errorNames = [
35+
self::NO_SUCH_TIMEZONE_IDENTIFIER_ERROR => 'NO_SUCH_TIMEZONE_IDENTIFIER_ERROR',
36+
self::NO_SUCH_TIMEZONE_IDENTIFIER_IN_ZONE_ERROR => 'NO_SUCH_TIMEZONE_IDENTIFIER_IN_ZONE_ERROR',
37+
self::NO_SUCH_TIMEZONE_IDENTIFIER_IN_COUNTRY_ERROR => 'NO_SUCH_TIMEZONE_IDENTIFIER_IN_COUNTRY_ERROR',
38+
];
39+
40+
/**
41+
* {@inheritdoc}
42+
*/
43+
public function __construct(array $options = null)
44+
{
45+
parent::__construct($options);
46+
47+
if ($this->countryCode && \DateTimeZone::PER_COUNTRY !== $this->zone) {
48+
throw new ConstraintDefinitionException('The option "countryCode" can only be used when "zone" option is configured with `\DateTimeZone::PER_COUNTRY`.');
49+
}
50+
}
51+
}
+91Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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\Validator\Constraints;
13+
14+
use Symfony\Component\Validator\Constraint;
15+
use Symfony\Component\Validator\ConstraintValidator;
16+
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
17+
18+
/**
19+
* Validates whether a value is a valid timezone identifier.
20+
*
21+
* @author Javier Spagnoletti <phansys@gmail.com>
22+
* @author Hugo Hamon <hugohamon@neuf.fr>
23+
*/
24+
class TimezoneValidator extends ConstraintValidator
25+
{
26+
/**
27+
* {@inheritdoc}
28+
*/
29+
public function validate($value, Constraint $constraint)
30+
{
31+
if (!$constraint instanceof Timezone) {
32+
throw new UnexpectedTypeException($constraint, Timezone::class);
33+
}
34+
35+
if (null === $value || '' === $value) {
36+
return;
37+
}
38+
39+
if (!is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) {
40+
throw new UnexpectedTypeException($value, 'string');
41+
}
42+
43+
$value = (string) $value;
44+
45+
// @see: https://bugs.php.net/bug.php?id=75928
46+
if ($constraint->countryCode) {
47+
$timezoneIds = \DateTimeZone::listIdentifiers($constraint->zone, $constraint->countryCode);
48+
} else {
49+
$timezoneIds = \DateTimeZone::listIdentifiers($constraint->zone);
50+
}
51+
52+
if ($timezoneIds && \in_array($value, $timezoneIds, true)) {
53+
return;
54+
}
55+
56+
if ($constraint->countryCode) {
57+
$code = Timezone::NO_SUCH_TIMEZONE_IDENTIFIER_IN_COUNTRY_ERROR;
58+
} elseif (\DateTimeZone::ALL !== $constraint->zone) {
59+
$code = Timezone::NO_SUCH_TIMEZONE_IDENTIFIER_IN_ZONE_ERROR;
60+
} else {
61+
$code = Timezone::NO_SUCH_TIMEZONE_IDENTIFIER_ERROR;
62+
}
63+
64+
$this->context->buildViolation($constraint->message)
65+
->setParameter('{{ value }}', $this->formatValue($value))
66+
->setCode($code)
67+
->addViolation();
68+
}
69+
70+
/**
71+
* {@inheritdoc}
72+
*/
73+
public function getDefaultOption()
74+
{
75+
return 'zone';
76+
}
77+
78+
/**
79+
* {@inheritdoc}
80+
*/
81+
protected function formatValue($value, $format = 0)
82+
{
83+
$value = parent::formatValue($value, $format);
84+
85+
if (!$value || \DateTimeZone::PER_COUNTRY === $value) {
86+
return $value;
87+
}
88+
89+
return array_search($value, (new \ReflectionClass(\DateTimeZone::class))->getConstants(), true) ?: $value;
90+
}
91+
}

‎src/Symfony/Component/Validator/Resources/translations/validators.en.xlf

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Resources/translations/validators.en.xlf
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@
354354
<source>This collection should contain only unique elements.</source>
355355
<target>This collection should contain only unique elements.</target>
356356
</trans-unit>
357+
<trans-unit id="92">
358+
<source>This value is not a valid timezone.</source>
359+
<target>This value is not a valid timezone.</target>
360+
</trans-unit>
357361
</body>
358362
</file>
359363
</xliff>

‎src/Symfony/Component/Validator/Resources/translations/validators.es.xlf

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Resources/translations/validators.es.xlf
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,10 @@
330330
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
331331
<target>Este Código de Identificación Bancaria (BIC) no está asociado con el IBAN {{ iban }}.</target>
332332
</trans-unit>
333+
<trans-unit id="92">
334+
<source>This value is not a valid timezone.</source>
335+
<target>Este valor no es una zona horaria válida.</target>
336+
</trans-unit>
333337
</body>
334338
</file>
335339
</xliff>

‎src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,10 @@
334334
<source>This value should be valid JSON.</source>
335335
<target>Cette valeur doit être un JSON valide.</target>
336336
</trans-unit>
337+
<trans-unit id="92">
338+
<source>This value is not a valid timezone.</source>
339+
<target>Cette valeur n'est pas un identifiant de fuseau horaire valide.</target>
340+
</trans-unit>
337341
</body>
338342
</file>
339343
</xliff>
+63Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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\Validator\Tests\Constraints;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Validator\Constraints\Timezone;
16+
17+
/**
18+
* @author Javier Spagnoletti <phansys@gmail.com>
19+
*/
20+
class TimezoneTest extends TestCase
21+
{
22+
public function testValidTimezoneConstraints()
23+
{
24+
$constraint = new Timezone();
25+
26+
$constraint = new Timezone([
27+
'message' => 'myMessage',
28+
'zone' => \DateTimeZone::PER_COUNTRY,
29+
'countryCode' => 'AR',
30+
]);
31+
32+
$constraint = new Timezone([
33+
'message' => 'myMessage',
34+
'zone' => \DateTimeZone::ALL,
35+
]);
36+
37+
// Make an assertion in order to avoid this test to be marked as risky
38+
$this->assertInstanceOf(Timezone::class, $constraint);
39+
}
40+
41+
/**
42+
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
43+
*/
44+
public function testExceptionForGroupedTimezonesByCountryWithWrongTimezone()
45+
{
46+
$constraint = new Timezone([
47+
'message' => 'myMessage',
48+
'zone' => \DateTimeZone::ALL,
49+
'countryCode' => 'AR',
50+
]);
51+
}
52+
53+
/**
54+
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
55+
*/
56+
public function testExceptionForGroupedTimezonesByCountryWithoutTimezone()
57+
{
58+
$constraint = new Timezone([
59+
'message' => 'myMessage',
60+
'countryCode' => 'AR',
61+
]);
62+
}
63+
}

0 commit comments

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