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 6783f94

Browse filesBrowse files
phansyshhamon
authored andcommitted
Add new TimezoneValidator
1 parent 5fe3701 commit 6783f94
Copy full SHA for 6783f94

File tree

6 files changed

+489
-0
lines changed
Filter options

6 files changed

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

‎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
@@ -350,6 +350,10 @@
350350
<source>This value should be either negative or zero.</source>
351351
<target>This value should be either negative or zero.</target>
352352
</trans-unit>
353+
<trans-unit id="91">
354+
<source>This value is not a valid timezone.</source>
355+
<target>This value is not a valid timezone.</target>
356+
</trans-unit>
353357
</body>
354358
</file>
355359
</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="91">
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>
+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(array(
27+
'message' => 'myMessage',
28+
'zone' => \DateTimeZone::PER_COUNTRY,
29+
'countryCode' => 'AR',
30+
));
31+
32+
$constraint = new Timezone(array(
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(array(
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(array(
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.