Skip to content

Commit

Permalink
Refactor Spain country handler to support more Spanish TIN
Browse files Browse the repository at this point in the history
  • Loading branch information
alphp committed Apr 19, 2024
1 parent d4ea9c6 commit 093bb3d
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 53 deletions.
2 changes: 1 addition & 1 deletion spec/loophp/Tin/CountryHandler/SpainSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ class SpainSpec extends AbstractAlgorithmSpec

public const INVALID_NUMBER_PATTERN = 'wwwwwwwww';

public const VALID_NUMBER = ['54237A', 'X1234567L', 'Z1234567R', 'M2812345C'];
public const VALID_NUMBER = ['54237A', 'X1234567L', 'Z1234567R', 'M2812345C', 'B05327986', 'P2009300A'];
}
2 changes: 1 addition & 1 deletion src/CountryHandler/CountryHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,6 @@ protected function matchLength(string $tin, int $length): bool

protected function matchPattern(string $subject, string $pattern): bool
{
return 1 === preg_match(sprintf('/%s/', $pattern), $subject);
return 1 === preg_match(sprintf('/%s/i', $pattern), $subject);
}
}
103 changes: 52 additions & 51 deletions src/CountryHandler/Spain.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

namespace loophp\Tin\CountryHandler;

use function strlen;

use const STR_PAD_LEFT;

/**
Expand All @@ -31,23 +29,17 @@ final class Spain extends CountryHandler
/**
* @var string
*/
public const PATTERN_1 = '\\d{8}[a-zA-Z]';
public const PATTERN_1 = '(^[XYZ\d]\d{7})([TRWAGMYFPDXBNJZSQVHLCKE]$)';

/**
* @var string
*/
public const PATTERN_2 = '[XYZKLMxyzklm]\\d{7}[a-zA-Z]';
public const PATTERN_2 = '(^[ABCDEFGHIJKLMUV])(\d{7})(\d$)';

/**
* @var array<int, string>
* @var string
*/
private static $tabConvertToChar = [
'T', 'R', 'W', 'A', 'G',
'M', 'Y', 'F', 'P', 'D',
'X', 'B', 'N', 'J', 'Z',
'S', 'Q', 'V', 'H', 'L',
'C', 'K', 'E',
];
public const PATTERN_3 = '(^[KLMNPQRSW])(\d{7})([JABCDEFGHI]$)';

public function getTIN(): string
{
Expand All @@ -56,38 +48,12 @@ public function getTIN(): string

protected function hasValidPattern(string $tin): bool
{
return $this->isFollowPattern1($tin) || $this->isFollowPattern2($tin);
return $this->isFollowPattern1($tin) || $this->isFollowPattern2($tin) || $this->isFollowPattern3($tin);
}

protected function hasValidRule(string $tin): bool
{
return ($this->isFollowPattern1($tin) && $this->isFollowRule1($tin))
|| ($this->isFollowPattern2($tin) && $this->isFollowRule2($tin));
}

private function getCharFromNumber(int $sum): string
{
return self::$tabConvertToChar[$sum - 1];
}

private function getNumberFromChar(string $m): int
{
switch ($m) {
case 'K':
case 'L':
case 'M':
case 'X':
return 0;

case 'Y':
return 1;

case 'Z':
return 2;

default:
return -1;
}
return $this->isFollowRule1($tin) || $this->isFollowRule2($tin) || $this->isFollowRule3($tin);
}

private function isFollowPattern1(string $tin): bool
Expand All @@ -100,24 +66,59 @@ private function isFollowPattern2(string $tin): bool
return $this->matchPattern($tin, self::PATTERN_2);
}

private function isFollowPattern3(string $tin): bool
{
return $this->matchPattern($tin, self::PATTERN_3);
}

private function isFollowRule1(string $tin): bool
{
$number = (int) (substr($tin, 0, strlen($tin) - 1));
$checkDigit = $tin[strlen($tin) - 1];
$remainderBy23 = $number % 23;
$sum = $remainderBy23 + 1;
if (1 !== preg_match('~' . self::PATTERN_1 . '~', strtoupper($tin), $parts)) {
return false;
}

$control = 'TRWAGMYFPDXBNJZSQVHLCKE';
$nie = ['X', 'Y', 'Z'];

return $this->getCharFromNumber($sum) === $checkDigit;
$nif = (int) str_replace($nie, array_keys($nie), $parts[1]);

$cheksum = substr($control, $nif % 23, 1);

return $parts[2] === $cheksum;
}

private function isFollowRule2(string $tin): bool
{
$c1 = (string) $this->getNumberFromChar($tin[0]);
$number = (int) ($c1 . substr($tin, 1, strlen($tin)));
$checkDigit = $tin[strlen($tin) - 1];
$remainderBy23 = $number % 23;
$sum = $remainderBy23 + 1;
if (1 !== preg_match('~' . self::PATTERN_2 . '~', strtoupper($tin), $parts)) {
return false;
}

$checksum = 0;

foreach (str_split($parts[2]) as $pos => $val) {
$checksum += array_sum(str_split((string) ((int) $val * (2 - ($pos % 2)))));
}

$checksum = (string) ((10 - ($checksum % 10)) % 10);

return $parts[3] === $checksum;
}

private function isFollowRule3(string $tin): bool
{
if (1 !== preg_match('~' . self::PATTERN_3 . '~', strtoupper($tin), $parts)) {
return false;
}

$control = 'JABCDEFGHI';
$checksum = 0;

foreach (str_split($parts[2]) as $pos => $val) {
$checksum += array_sum(str_split((string) ((int) $val * (2 - ($pos % 2)))));
}

$checksum = substr($control, ((10 - ($checksum % 10)) % 10), 1);

return $this->getCharFromNumber($sum) === $checkDigit;
return $parts[3] === $checksum;
}
}

0 comments on commit 093bb3d

Please sign in to comment.