mirror of
https://github.com/Respect/Validation.git
synced 2024-06-08 00:32:16 +02:00
Added Finnish personal identity code rule and tests.
This commit is contained in:
parent
52b75bc1ed
commit
35d8d2e0c7
69
library/Rules/Hetu.php
Normal file
69
library/Rules/Hetu.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (c) Ville Hukkamäki <vhukkamaki@gmail.com>
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Validation\Rules;
|
||||
|
||||
use Respect\Validation\Message\Template;
|
||||
use Respect\Validation\Rules\Core\Simple;
|
||||
|
||||
use function is_string;
|
||||
use function preg_match;
|
||||
use function strtoupper;
|
||||
|
||||
/**
|
||||
* @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
|
||||
{
|
||||
public function validate(mixed $input): bool
|
||||
{
|
||||
if (!is_string($input)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$input = strtoupper($input);
|
||||
|
||||
if (!preg_match('/^(\d{2})(\d{2})(\d{2})([+\-A-FU-Y])(\d{3})([0-9A-FHJ-NPR-Y])$/', $input, $m)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$century = match ($m[4]) {
|
||||
'+' => '18',
|
||||
'-','U','V','W','X','Y' => '19',
|
||||
'A','B','C','D','E','F' => '20',
|
||||
default => null,
|
||||
};
|
||||
|
||||
if ($century === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$dateRule = new Date();
|
||||
if (!$dateRule->evaluate($century . $m[3] . '-' . $m[2] . '-' . $m[1])->isValid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getChecksum($m[1] . $m[2] . $m[3] . $m[5]) === $m[6];
|
||||
}
|
||||
|
||||
private function getChecksum(string $s): string
|
||||
{
|
||||
$mod = (int)$s % 31;
|
||||
$tab = [
|
||||
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','H','J','K','L','M','N','P',
|
||||
'R','S','T','U','C','W','X','Y',
|
||||
];
|
||||
|
||||
return $tab[$mod];
|
||||
}
|
||||
}
|
66
tests/unit/Rules/HetuTest.php
Normal file
66
tests/unit/Rules/HetuTest.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (c) Ville Hukkamäki <vhukkamaki@gmail.com>
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Respect\Validation\Rules;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use Respect\Validation\Test\RuleTestCase;
|
||||
|
||||
#[Group('rule')]
|
||||
#[CoversClass(Hetu::class)]
|
||||
final class HetuTest extends RuleTestCase
|
||||
{
|
||||
/** @return iterable<array{Hetu, mixed}> */
|
||||
public static function providerForValidInput(): iterable
|
||||
{
|
||||
$rule = new Hetu();
|
||||
|
||||
return [
|
||||
[$rule, '010106A9012'],
|
||||
[$rule, '290199-907A'],
|
||||
[$rule, '010199+9012'],
|
||||
[$rule, '280291+913L'],
|
||||
[$rule, '280291+923X'],
|
||||
];
|
||||
}
|
||||
|
||||
/** @return iterable<array{Hetu, mixed}> */
|
||||
public static function providerForInvalidInput(): iterable
|
||||
{
|
||||
$rule = new Hetu();
|
||||
|
||||
return [
|
||||
[$rule, '010106_9012'],
|
||||
[$rule, '010106G9012'],
|
||||
[$rule, '010106Z9012'],
|
||||
[$rule, '010106A901G'],
|
||||
[$rule, '010106A901I'],
|
||||
[$rule, '010106A901O'],
|
||||
[$rule, '010106A901Q'],
|
||||
[$rule, '010106A901Z'],
|
||||
[$rule, '010106!9012'],
|
||||
[$rule, '010106'],
|
||||
[$rule, '01X199+9012'],
|
||||
[$rule, '01X199Z9012'],
|
||||
[$rule, '01X199T9012'],
|
||||
[$rule, '999999A9999'],
|
||||
[$rule, '999999A999F'],
|
||||
[$rule, '300201A1236'],
|
||||
[$rule, '290201A123J'],
|
||||
|
||||
[$rule, null],
|
||||
[$rule, []],
|
||||
[$rule, false],
|
||||
[$rule, 42],
|
||||
[$rule, '127.0.0.1'],
|
||||
[$rule, new DateTime()],
|
||||
];
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue