mirror of
https://github.com/Respect/Validation.git
synced 2024-06-01 13:22:24 +02:00
Create "Hetu" rule
This rule validates Finnish personal identity codes. Co-authored-by: Henrique Moody <henriquemoody@gmail.com>
This commit is contained in:
parent
52b75bc1ed
commit
a5d042be7b
|
@ -108,6 +108,7 @@
|
|||
- [Cnh](rules/Cnh.md)
|
||||
- [Cnpj](rules/Cnpj.md)
|
||||
- [Cpf](rules/Cpf.md)
|
||||
- [Hetu](rules/Hetu.md)
|
||||
- [Imei](rules/Imei.md)
|
||||
- [Isbn](rules/Isbn.md)
|
||||
- [Luhn](rules/Luhn.md)
|
||||
|
@ -344,6 +345,7 @@
|
|||
- [Graph](rules/Graph.md)
|
||||
- [GreaterThan](rules/GreaterThan.md)
|
||||
- [GreaterThanOrEqual](rules/GreaterThanOrEqual.md)
|
||||
- [Hetu](rules/Hetu.md)
|
||||
- [HexRgbColor](rules/HexRgbColor.md)
|
||||
- [Iban](rules/Iban.md)
|
||||
- [Identical](rules/Identical.md)
|
||||
|
|
|
@ -24,6 +24,7 @@ See also:
|
|||
- [Bsn](Bsn.md)
|
||||
- [Cnpj](Cnpj.md)
|
||||
- [Cpf](Cpf.md)
|
||||
- [Hetu](Hetu.md)
|
||||
- [Imei](Imei.md)
|
||||
- [NfeAccessKey](NfeAccessKey.md)
|
||||
- [Nif](Nif.md)
|
||||
|
|
|
@ -21,6 +21,7 @@ See also:
|
|||
- [Bsn](Bsn.md)
|
||||
- [Cnh](Cnh.md)
|
||||
- [Cpf](Cpf.md)
|
||||
- [Hetu](Hetu.md)
|
||||
- [Imei](Imei.md)
|
||||
- [NfeAccessKey](NfeAccessKey.md)
|
||||
- [Nif](Nif.md)
|
||||
|
|
|
@ -37,6 +37,7 @@ See also:
|
|||
- [Bsn](Bsn.md)
|
||||
- [Cnh](Cnh.md)
|
||||
- [Cnpj](Cnpj.md)
|
||||
- [Hetu](Hetu.md)
|
||||
- [Imei](Imei.md)
|
||||
- [NfeAccessKey](NfeAccessKey.md)
|
||||
- [Nif](Nif.md)
|
||||
|
|
37
docs/rules/Hetu.md
Normal file
37
docs/rules/Hetu.md
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Hetu
|
||||
|
||||
- `Hetu()`
|
||||
|
||||
Validates a Finnish personal identity code ([HETU][]).
|
||||
|
||||
```php
|
||||
v::hetu()->validate('010106A9012'); // true
|
||||
v::hetu()->validate('290199-907A'); // true
|
||||
v::hetu()->validate('280291+923X'); // true
|
||||
|
||||
v::hetu()->validate('010106_9012'); // false
|
||||
```
|
||||
|
||||
The validation is case-sensitive.
|
||||
|
||||
## Categorization
|
||||
|
||||
- Identifications
|
||||
|
||||
## Changelog
|
||||
|
||||
| Version | Description |
|
||||
|--------:|-------------|
|
||||
| 3.0.0 | Created |
|
||||
|
||||
***
|
||||
See also:
|
||||
|
||||
- [Cnh](Cnh.md)
|
||||
- [Cnpj](Cnpj.md)
|
||||
- [Cpf](Cpf.md)
|
||||
- [Imei](Imei.md)
|
||||
- [Nif](Nif.md)
|
||||
- [PortugueseNif](PortugueseNif.md)
|
||||
|
||||
[HETU]: https://en.wikipedia.org/wiki/National_identification_number#Finland
|
|
@ -26,6 +26,7 @@ See also:
|
|||
- [Cnh](Cnh.md)
|
||||
- [Cnpj](Cnpj.md)
|
||||
- [Cpf](Cpf.md)
|
||||
- [Hetu](Hetu.md)
|
||||
- [Isbn](Isbn.md)
|
||||
- [Luhn](Luhn.md)
|
||||
|
||||
|
|
|
@ -26,4 +26,5 @@ See also:
|
|||
- [Cnh](Cnh.md)
|
||||
- [Cnpj](Cnpj.md)
|
||||
- [Cpf](Cpf.md)
|
||||
- [Hetu](Hetu.md)
|
||||
- [PortugueseNif](PortugueseNif.md)
|
||||
|
|
|
@ -26,4 +26,5 @@ See also:
|
|||
- [Cnh](Cnh.md)
|
||||
- [Cnpj](Cnpj.md)
|
||||
- [Cpf](Cpf.md)
|
||||
- [Hetu](Hetu.md)
|
||||
- [Nif](Nif.md)
|
||||
|
|
|
@ -138,6 +138,8 @@ interface ChainedValidator extends Validatable
|
|||
|
||||
public function greaterThan(mixed $compareTo): ChainedValidator;
|
||||
|
||||
public function hetu(): ChainedValidator;
|
||||
|
||||
public function hexRgbColor(): ChainedValidator;
|
||||
|
||||
public function iban(): ChainedValidator;
|
||||
|
|
|
@ -140,6 +140,8 @@ interface StaticValidator
|
|||
|
||||
public static function greaterThan(mixed $compareTo): ChainedValidator;
|
||||
|
||||
public static function hetu(): ChainedValidator;
|
||||
|
||||
public static function hexRgbColor(): ChainedValidator;
|
||||
|
||||
public static function iban(): ChainedValidator;
|
||||
|
|
58
library/Rules/Hetu.php
Normal file
58
library/Rules/Hetu.php
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Validation\Rules;
|
||||
|
||||
use Respect\Validation\Helpers\CanValidateDateTime;
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Rules\Core\Simple;
|
||||
|
||||
use function is_string;
|
||||
use function preg_match;
|
||||
use function str_split;
|
||||
|
||||
/**
|
||||
* @see https://en.wikipedia.org/wiki/National_identification_number#Finland
|
||||
*/
|
||||
#[Template(
|
||||
'{{name}} must be a valid Finnish personal identity code',
|
||||
'{{name}} must not be a valid Finnish personal identity code',
|
||||
)]
|
||||
final class Hetu extends Simple
|
||||
{
|
||||
use CanValidateDateTime;
|
||||
|
||||
public function validate(mixed $input): bool
|
||||
{
|
||||
if (!is_string($input)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!preg_match('/^(\d{2})(\d{2})(\d{2})([+\-A-FU-Y])(\d{3})([0-9A-FHJ-NPR-Y])$/', $input, $matches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
[, $day, $month, $year, $centuryMarker, $individualNumber, $controlCharacter] = $matches;
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
$century = match ($centuryMarker) {
|
||||
'+' => '18',
|
||||
'-', 'U', 'V', 'W', 'X', 'Y' => '19',
|
||||
'A', 'B', 'C', 'D', 'E', 'F' => '20',
|
||||
};
|
||||
if (!$this->isDateTime('dmY', $day . $month . $century . $year)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $day . $month . $year . $individualNumber;
|
||||
$validationKeys = str_split('0123456789ABCDEFHJKLMNPRSTUVWXY');
|
||||
|
||||
return $validationKeys[$id % 31] === $controlCharacter;
|
||||
}
|
||||
}
|
49
tests/integration/rules/hetu.phpt
Normal file
49
tests/integration/rules/hetu.phpt
Normal file
|
@ -0,0 +1,49 @@
|
|||
--FILE--
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
use Respect\Validation\Validator as v;
|
||||
|
||||
run([
|
||||
'Default' => [v::hetu(), '010106A901O'],
|
||||
'Negative' => [v::not(v::hetu()), '010106A9012'],
|
||||
'With template' => [v::hetu(), '010106A901O', 'That is not a HETU'],
|
||||
'With name' => [v::hetu()->setName('Hetu'), '010106A901O'],
|
||||
]);
|
||||
?>
|
||||
--EXPECT--
|
||||
Default
|
||||
⎺⎺⎺⎺⎺⎺⎺
|
||||
"010106A901O" must be a valid Finnish personal identity code
|
||||
- "010106A901O" must be a valid Finnish personal identity code
|
||||
[
|
||||
'hetu' => '"010106A901O" must be a valid Finnish personal identity code',
|
||||
]
|
||||
|
||||
Negative
|
||||
⎺⎺⎺⎺⎺⎺⎺⎺
|
||||
"010106A9012" must not be a valid Finnish personal identity code
|
||||
- "010106A9012" must not be a valid Finnish personal identity code
|
||||
[
|
||||
'hetu' => '"010106A9012" must not be a valid Finnish personal identity code',
|
||||
]
|
||||
|
||||
With template
|
||||
⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺⎺
|
||||
That is not a HETU
|
||||
- That is not a HETU
|
||||
[
|
||||
'hetu' => 'That is not a HETU',
|
||||
]
|
||||
|
||||
With name
|
||||
⎺⎺⎺⎺⎺⎺⎺⎺⎺
|
||||
Hetu must be a valid Finnish personal identity code
|
||||
- Hetu must be a valid Finnish personal identity code
|
||||
[
|
||||
'Hetu' => 'Hetu must be a valid Finnish personal identity code',
|
||||
]
|
||||
|
79
tests/unit/Rules/HetuTest.php
Normal file
79
tests/unit/Rules/HetuTest.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (c) Alexandre Gomes Gaigalas <alganet@gmail.com>
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Validation\Rules;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Respect\Validation\Test\TestCase;
|
||||
|
||||
#[Group('rule')]
|
||||
#[CoversClass(Hetu::class)]
|
||||
final class HetuTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
#[DataProvider('providerForNonStringTypes')]
|
||||
public function itShouldAlwaysInvalidateWhenValueIsNotString(mixed $input): void
|
||||
{
|
||||
self::assertInvalidInput(new Hetu(), $input);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[DataProvider('providerForInvalidHetu')]
|
||||
public function itShouldInvalidateInvalidHetu(string $input): void
|
||||
{
|
||||
self::assertInvalidInput(new Hetu(), $input);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
#[DataProvider('providerForValidHetu')]
|
||||
public function itShouldValidateValidHetu(string $input): void
|
||||
{
|
||||
self::assertValidInput(new Hetu(), $input);
|
||||
}
|
||||
|
||||
/** @return array<array{string}> */
|
||||
public static function providerForValidHetu(): array
|
||||
{
|
||||
return [
|
||||
['010106A9012'],
|
||||
['290199-907A'],
|
||||
['010199+9012'],
|
||||
['280291+913L'],
|
||||
['280291+923X'],
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<array{string}> */
|
||||
public static function providerForInvalidHetu(): array
|
||||
{
|
||||
return [
|
||||
['010106a9012'],
|
||||
['010106_9012'],
|
||||
['010106G9012'],
|
||||
['010106Z9012'],
|
||||
['010106A901G'],
|
||||
['010106A901I'],
|
||||
['010106A901O'],
|
||||
['010106A901Q'],
|
||||
['010106A901Z'],
|
||||
['010106!9012'],
|
||||
['010106'],
|
||||
['01X199+9012'],
|
||||
['01X199Z9012'],
|
||||
['01X199T9012'],
|
||||
['999999A9999'],
|
||||
['999999A999F'],
|
||||
['300201A1236'],
|
||||
['290201A123J'],
|
||||
];
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue