FIAlgorithm::isFollowFinlandRule()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 6
rs 10
1
<?php
2
3
namespace LeKoala\Tin\Algo;
4
5
use LeKoala\Tin\Util\DateUtil;
6
use LeKoala\Tin\Util\StringUtil;
7
8
/**
9
 * Finland
10
 */
11
class FIAlgorithm extends TINAlgorithm
12
{
13
    const LENGTH = 11;
14
    const PATTERN = "[0-3]\\d[0-1]\\d{3}[+-A]\\d{3}[0-9A-Z]";
15
16
    public function validate(string $tin)
17
    {
18
        if (!$this->isFollowLength($tin)) {
19
            return StatusCode::INVALID_LENGTH;
20
        }
21
        if (!$this->isFollowPattern($tin) || !$this->isValidDate($tin)) {
22
            return StatusCode::INVALID_PATTERN;
23
        }
24
        if (!$this->isFollowRules($tin)) {
25
            return StatusCode::INVALID_SYNTAX;
26
        }
27
        return StatusCode::VALID;
28
    }
29
30
    public function isFollowLength(string $tin)
31
    {
32
        return StringUtil::isFollowLength($tin, self::LENGTH);
33
    }
34
35
    public function isFollowPattern(string $tin)
36
    {
37
        return StringUtil::isFollowPattern($tin, self::PATTERN);
38
    }
39
40
    public function isFollowRules(string $tin)
41
    {
42
        return $this->isFollowFinlandRule($tin);
43
    }
44
45
    public function isFollowFinlandRule(string $tin)
46
    {
47
        $number = intval(StringUtil::substring($tin, 0, 6) . StringUtil::substring($tin, 7, 10));
48
        $remainderBy31 = $number % 31;
49
        $c11 = $tin[10];
50
        return $this->getMatch($remainderBy31) == $c11;
51
    }
52
53
    public function getMatch($number)
54
    {
55
        if ($number < 10) {
56
            return StringUtil::forDigit($number, 10);
57
        }
58
        switch ($number) {
59
            case 10:
60
                return 'A';
61
            case 11:
62
                return 'B';
63
            case 12:
64
                return 'C';
65
            case 13:
66
                return 'D';
67
            case 14:
68
                return 'E';
69
            case 15:
70
                return 'F';
71
            case 16:
72
                return 'H';
73
            case 17:
74
                return 'J';
75
            case 18:
76
                return 'K';
77
            case 19:
78
                return 'L';
79
            case 20:
80
                return 'M';
81
            case 21:
82
                return 'N';
83
            case 22:
84
                return 'P';
85
            case 23:
86
                return 'R';
87
            case 24:
88
                return 'S';
89
            case 25:
90
                return 'T';
91
            case 26:
92
                return 'U';
93
            case 27:
94
                return 'V';
95
            case 28:
96
                return 'W';
97
            case 29:
98
                return 'X';
99
            case 30:
100
                return 'Y';
101
            default:
102
                return ' ';
103
        }
104
    }
105
106
    private function isValidDate(string $tin)
107
    {
108
        $day = intval(StringUtil::substring($tin, 0, 2));
109
        $month = intval(StringUtil::substring($tin, 2, 4));
110
        $year = intval(StringUtil::substring($tin, 4, 6));
111
        $c7 = StringUtil::substring($tin, 6, 7);
112
        if ("+" == $c7) {
113
            return DateUtil::validate(1800 + $year, $month, $day);
114
        }
115
        if ("-" == $c7) {
116
            return DateUtil::validate(1900 + $year, $month, $day);
117
        }
118
        return "A" == $c7 && DateUtil::validate(2000 + $year, $month, $day);
119
    }
120
}
121