-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #36 from programmatordev/1.x
1.x
- Loading branch information
Showing
10 changed files
with
223 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Timezone | ||
|
||
Validates that a value is a valid timezone identifier. | ||
|
||
```php | ||
Timezone( | ||
string $timezoneGroup = \DateTimeZone::ALL, | ||
?string $countryCode = null, | ||
string $message = 'The "{{ name }}" value is not a valid timezone, "{{ value }}" given.' | ||
); | ||
``` | ||
|
||
## Basic Usage | ||
|
||
```php | ||
// All timezone identifiers | ||
Validator::timezone()->validate('Europe/Lisbon'); // true | ||
|
||
// Restrict timezone identifiers to a specific geographical zone | ||
Validator::timezone(timezoneGroup: \DateTimeZone::EUROPE)->validate('Europe/Lisbon'); // true | ||
Validator::timezone(timezoneGroup: \DateTimeZone::AFRICA)->validate('Europe/Lisbon'); // false | ||
// Or multiple geographical zones | ||
Validator::timezone(timezoneGroup: \DateTimeZone::AFRICA | \DateTimeZone::EUROPE)->validate('Europe/Lisbon'); // true | ||
|
||
// Restrict timezone identifiers to a specific country | ||
Validator::timezone(timezoneGroup: \DateTimeZone::PER_COUNTRY, countryCode: 'pt')->validate('Europe/Lisbon'); // true | ||
Validator::timezone(timezoneGroup: \DateTimeZone::PER_COUNTRY, countryCode: 'en')->validate('Europe/Lisbon'); // false | ||
``` | ||
|
||
> **Note** | ||
> An `UnexpectedValueException` will be thrown when the `timezoneGroup` value is `\DateTimeZone::PER_COUNTRY` | ||
> and the `countryCode` value is `null` (not provided). | ||
> **Note** | ||
> An `UnexpectedValueException` will be thrown when the `countryCode` value is not valid. | ||
> Only if the `timezoneGroup` value is `\DateTimeZone::PER_COUNTRY`, otherwise it is ignored. | ||
## Options | ||
|
||
### `timezoneGroup` | ||
|
||
type: `int` default: `\DateTimeZone::ALL` | ||
|
||
Set this option to restrict timezone identifiers to a specific geographical zone. | ||
|
||
Available timezone groups: | ||
|
||
- `\DateTimeZone::AFRICA` | ||
- `\DateTimeZone::AMERICA` | ||
- `\DateTimeZone::ANTARCTICA` | ||
- `\DateTimeZone::ARCTIC` | ||
- `\DateTimeZone::ASIA` | ||
- `\DateTimeZone::ATLANTIC` | ||
- `\DateTimeZone::AUSTRALIA` | ||
- `\DateTimeZone::EUROPE` | ||
- `\DateTimeZone::INDIAN` | ||
- `\DateTimeZone::PACIFIC` | ||
|
||
In addition, there are special timezone groups: | ||
|
||
- `\DateTimeZone::ALL` all timezones; | ||
- `\DateTimeZone::ALL_WITH_BC` all timezones including deprecated timezones; | ||
- `\DateTimeZone::PER_COUNTRY` timezones per country (must be used together with the [`countryCode`](#countrycode) option); | ||
- `\DateTimeZone::UTC` UTC timezones. | ||
|
||
### `countryCode` | ||
|
||
type: `?string` default: `null` | ||
|
||
If the `timezoneGroup` option value is `\DateTimeZone::PER_COUNTRY`, | ||
this option is required to restrict valid timezone identifiers to the ones that belong to the given country. | ||
|
||
Must be a valid alpha-2 country code. | ||
Check the [official country codes](https://en.wikipedia.org/wiki/ISO_3166-1#Current_codes) list for more information. | ||
|
||
### `message` | ||
|
||
type `string` default: `The "{{ name }}" value is not a valid timezone, "{{ value }}" given.` | ||
|
||
Message that will be shown if the input value is not a valid timezone. | ||
|
||
The following parameters are available: | ||
|
||
| Parameter | Description | | ||
|---------------------|---------------------------| | ||
| `{{ value }}` | The current invalid value | | ||
| `{{ name }}` | Name of the invalid value | | ||
| `{{ countryCode }}` | Selected country code | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php | ||
|
||
namespace ProgrammatorDev\YetAnotherPhpValidator\Exception; | ||
|
||
class TimezoneException extends ValidationException {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
<?php | ||
|
||
namespace ProgrammatorDev\YetAnotherPhpValidator\Rule; | ||
|
||
use ProgrammatorDev\YetAnotherPhpValidator\Exception\TimezoneException; | ||
use ProgrammatorDev\YetAnotherPhpValidator\Exception\UnexpectedValueException; | ||
use ProgrammatorDev\YetAnotherPhpValidator\Exception\ValidationException; | ||
use ProgrammatorDev\YetAnotherPhpValidator\Validator; | ||
|
||
class Timezone extends AbstractRule implements RuleInterface | ||
{ | ||
public function __construct( | ||
private readonly int $timezoneGroup = \DateTimeZone::ALL, | ||
private ?string $countryCode = null, | ||
private readonly string $message = 'The "{{ name }}" value is not a valid timezone, "{{ value }}" given.' | ||
) {} | ||
|
||
public function assert(mixed $value, string $name): void | ||
{ | ||
if ($this->timezoneGroup === \DateTimeZone::PER_COUNTRY) { | ||
// Country code is required when using PER_COUNTRY timezone group | ||
if ($this->countryCode === null) { | ||
throw new UnexpectedValueException( | ||
'A country code is required when timezone group is \DateTimeZone::PER_COUNTRY.' | ||
); | ||
} | ||
|
||
// Normalize country code | ||
$this->countryCode = strtoupper($this->countryCode); | ||
|
||
try { | ||
Validator::country()->assert($this->countryCode, 'countryCode'); | ||
} | ||
catch (ValidationException $exception) { | ||
throw new UnexpectedValueException($exception->getMessage()); | ||
} | ||
} | ||
|
||
if (!\in_array($value, \DateTimeZone::listIdentifiers($this->timezoneGroup, $this->countryCode), true)) { | ||
throw new TimezoneException( | ||
message: $this->message, | ||
parameters: [ | ||
'value' => $value, | ||
'name' => $name, | ||
'countryCode' => $this->countryCode | ||
] | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php | ||
|
||
namespace ProgrammatorDev\YetAnotherPhpValidator\Test; | ||
|
||
use ProgrammatorDev\YetAnotherPhpValidator\Exception\TimezoneException; | ||
use ProgrammatorDev\YetAnotherPhpValidator\Rule\Timezone; | ||
use ProgrammatorDev\YetAnotherPhpValidator\Test\Util\TestRuleFailureConditionTrait; | ||
use ProgrammatorDev\YetAnotherPhpValidator\Test\Util\TestRuleMessageOptionTrait; | ||
use ProgrammatorDev\YetAnotherPhpValidator\Test\Util\TestRuleSuccessConditionTrait; | ||
use ProgrammatorDev\YetAnotherPhpValidator\Test\Util\TestRuleUnexpectedValueTrait; | ||
|
||
class TimezoneTest extends AbstractTest | ||
{ | ||
use TestRuleUnexpectedValueTrait; | ||
use TestRuleFailureConditionTrait; | ||
use TestRuleSuccessConditionTrait; | ||
use TestRuleMessageOptionTrait; | ||
|
||
public static function provideRuleUnexpectedValueData(): \Generator | ||
{ | ||
$missingCountryCodeMessage = '/A country code is required when timezone group is \\\DateTimeZone::PER_COUNTRY./'; | ||
$invalidCountryCodeMessage = '/The "(.*)" value is not a valid "(.*)" country code, "(.*)" given./'; | ||
|
||
yield 'missing country code' => [new Timezone(\DateTimeZone::PER_COUNTRY), 'Europe/Lisbon', $missingCountryCodeMessage]; | ||
yield 'invalid country code' => [new Timezone(\DateTimeZone::PER_COUNTRY, 'PRT'), 'Europe/Lisbon', $invalidCountryCodeMessage]; | ||
} | ||
|
||
public static function provideRuleFailureConditionData(): \Generator | ||
{ | ||
$exception = TimezoneException::class; | ||
$message = '/The "(.*)" value is not a valid timezone, "(.*)" given./'; | ||
|
||
yield 'invalid timezone' => [new Timezone(), 'Invalid/Timezone', $exception, $message]; | ||
yield 'not of timezone group' => [new Timezone(\DateTimeZone::AFRICA), 'Europe/Lisbon', $exception, $message]; | ||
yield 'not of timezone country' => [new Timezone(\DateTimeZone::PER_COUNTRY, 'es'), 'Europe/Lisbon', $exception, $message]; | ||
} | ||
|
||
public static function provideRuleSuccessConditionData(): \Generator | ||
{ | ||
yield 'valid timezone' => [new Timezone(), 'Europe/Lisbon']; | ||
yield 'is of timezone group' => [new Timezone(\DateTimeZone::EUROPE), 'Europe/Lisbon']; | ||
yield 'is of multiple timezone groups' => [new Timezone(\DateTimeZone::EUROPE | \DateTimeZone::UTC), 'UTC']; | ||
yield 'is of timezone country' => [new Timezone(\DateTimeZone::PER_COUNTRY, 'pt'), 'Europe/Lisbon']; | ||
} | ||
|
||
public static function provideRuleMessageOptionData(): \Generator | ||
{ | ||
yield 'message' => [ | ||
new Timezone( | ||
message: 'The "{{ name }}" value "{{ value }}" is not a valid timezone.' | ||
), | ||
'Invalid/Timezone', | ||
'The "test" value "Invalid/Timezone" is not a valid timezone.' | ||
]; | ||
} | ||
|
||
} |