-
Notifications
You must be signed in to change notification settings - Fork 771
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This rule validates Finnish personal identity codes. Co-authored-by: Henrique Moody <[email protected]>
- Loading branch information
1 parent
52b75bc
commit a5d042b
Showing
13 changed files
with
235 additions
and
0 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
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,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 |
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 |
---|---|---|
|
@@ -26,4 +26,5 @@ See also: | |
- [Cnh](Cnh.md) | ||
- [Cnpj](Cnpj.md) | ||
- [Cpf](Cpf.md) | ||
- [Hetu](Hetu.md) | ||
- [Nif](Nif.md) |
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,58 @@ | ||
<?php | ||
|
||
/* | ||
* Copyright (c) Alexandre Gomes Gaigalas <[email protected]> | ||
* 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; | ||
} | ||
} |
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,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', | ||
] | ||
|
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,79 @@ | ||
<?php | ||
|
||
/* | ||
* Copyright (c) Alexandre Gomes Gaigalas <[email protected]> | ||
* 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'], | ||
]; | ||
} | ||
} |