SEAlgorithm::isFollowPatterns()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 4
c 2
b 0
f 0
nc 4
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\NumberUtil;
7
use LeKoala\Tin\Util\StringUtil;
8
use LeKoala\Tin\Exception\NegativeNumberException;
9
10
/**
11
 * Sweden
12
 */
13
class SEAlgorithm extends TINAlgorithm
14
{
15
    const LENGTH_1_AND_2 = 10;
16
    const PATTERN_1 = "\\d{2}[0-1]\\d[0-3]\\d{5}";
17
    const PATTERN_2 = "\\d{2}[0-1]\\d[6-9]\\d{5}";
18
    const LENGTH_3_AND_4 = 12;
19
    const PATTERN_3 = "(1[89]|20)\\d{2}(0[1-9]|1[012])(0[1-9]|[1-2][0-9]|3[0-1])\\d{4}";
20
    const PATTERN_4 = "(1[89]|20)\\d{2}(0[1-9]|1[012])(6[1-9]|[7-8][0-9]|9[0-1])\\d{4}";
21
22
    public function validate(string $tin)
23
    {
24
        $normalizedTIN = str_replace("-", "", $tin);
25
        $normalizedTIN = str_replace("+", "", $normalizedTIN);
26
        if (!$this->isFollowLength1And2($normalizedTIN) && !$this->isFollowLength3And4($normalizedTIN)) {
27
            return StatusCode::INVALID_LENGTH;
28
        }
29
        if (!$this->isFollowPatterns($normalizedTIN)) {
30
            return StatusCode::INVALID_PATTERN;
31
        }
32
        if (!$this->isFollowRules($normalizedTIN)) {
33
            return StatusCode::INVALID_SYNTAX;
34
        }
35
        return StatusCode::VALID;
36
    }
37
38
    public function isFollowPatterns(string $tin)
39
    {
40
        return $this->isFollowPatternAndIsValidDate($tin)
41
            || $this->isFollowPattern2AndIsValidDate2($tin)
42
            || $this->isFollowPattern3AndIsValidDate3($tin)
43
            || $this->isFollowPattern4AndIsValidDate4($tin);
44
    }
45
46
    public function isFollowPatternAndIsValidDate(string $tin)
47
    {
48
        return $this->isFollowPattern($tin) && $this->isValidDate($tin);
49
    }
50
51
    public function isFollowPattern2AndIsValidDate2(string $tin)
52
    {
53
        return $this->isFollowPattern2($tin) && $this->isValidDate2($tin);
54
    }
55
56
    public function isFollowPattern3AndIsValidDate3(string $tin)
57
    {
58
        return $this->isFollowPattern3($tin) && $this->isValidDate3($tin);
59
    }
60
61
    public function isFollowPattern4AndIsValidDate4(string $tin)
62
    {
63
        return $this->isFollowPattern4($tin) && $this->isValidDate4($tin);
64
    }
65
66
    public function isFollowRules(string $tin)
67
    {
68
        return (intval("10") == strlen($tin)
69
            && $this->isFollowSwedenRule1And2($tin))
70
            || (intval("12") == strlen($tin)
71
                && $this->isFollowSwedenRule3And4($tin));
72
    }
73
74
    public function isFollowLength1And2(string $tin)
75
    {
76
        return StringUtil::isFollowLength($tin, self::LENGTH_1_AND_2);
77
    }
78
79
    public function isFollowLength3And4(string $tin)
80
    {
81
        return StringUtil::isFollowLength($tin, self::LENGTH_3_AND_4);
82
    }
83
84
    public function isFollowPattern(string $tin)
85
    {
86
        return StringUtil::isFollowPattern($tin, self::PATTERN_1);
87
    }
88
89
    public function isFollowPattern2(string $tin)
90
    {
91
        return StringUtil::isFollowPattern($tin, self::PATTERN_2);
92
    }
93
94
    public function isFollowPattern3(string $tin)
95
    {
96
        return StringUtil::isFollowPattern($tin, self::PATTERN_3);
97
    }
98
99
    public function isFollowPattern4(string $tin)
100
    {
101
        return StringUtil::isFollowPattern($tin, self::PATTERN_4);
102
    }
103
104
    public function isFollowSwedenRule1And2(string $tin)
105
    {
106
        $c1 = StringUtil::digitAt($tin, 0);
107
        $c2 = StringUtil::digitAt($tin, 1);
108
        $c3 = StringUtil::digitAt($tin, 2);
109
        $c4 = StringUtil::digitAt($tin, 3);
110
        $c5 = StringUtil::digitAt($tin, 4);
111
        $c6 = StringUtil::digitAt($tin, 5);
112
        $c7 = StringUtil::digitAt($tin, 6);
113
        $c8 = StringUtil::digitAt($tin, 7);
114
        $c9 = StringUtil::digitAt($tin, 8);
115
        $c10 = StringUtil::digitAt($tin, 9);
116
        try {
117
            $sum = $c2 + $c4 + $c6 + $c8
118
                + NumberUtil::sumDigit($c1 * 2)
119
                + NumberUtil::sumDigit($c3 * 2)
120
                + NumberUtil::sumDigit($c5 * 2)
121
                + NumberUtil::sumDigit($c7 * 2)
122
                + NumberUtil::sumDigit($c9 * 2);
123
            $check = 10 - NumberUtil::getUnit($sum);
124
            if ($check != 10) {
125
                return $c10 == $check;
126
            }
127
            return $c10 == 0;
128
        } catch (NegativeNumberException $e) {
129
            return false;
130
        }
131
    }
132
133
    public function isFollowSwedenRule3And4(string $tin)
134
    {
135
        $c3 = StringUtil::digitAt($tin, 2);
136
        $c4 = StringUtil::digitAt($tin, 3);
137
        $c5 = StringUtil::digitAt($tin, 4);
138
        $c6 = StringUtil::digitAt($tin, 5);
139
        $c7 = StringUtil::digitAt($tin, 6);
140
        $c8 = StringUtil::digitAt($tin, 7);
141
        $c9 = StringUtil::digitAt($tin, 8);
142
        $c10 = StringUtil::digitAt($tin, 9);
143
        $c11 = StringUtil::digitAt($tin, 10);
144
        $c12 = StringUtil::digitAt($tin, 11);
145
        try {
146
            $sum = $c4 + $c6 + $c8 + $c10
147
                + NumberUtil::sumDigit($c3 * 2)
148
                + NumberUtil::sumDigit($c5 * 2)
149
                + NumberUtil::sumDigit($c7 * 2)
150
                + NumberUtil::sumDigit($c9 * 2)
151
                + NumberUtil::sumDigit($c11 * 2);
152
            $check = 10 - NumberUtil::getUnit($sum);
153
            if ($check != 10) {
154
                return $c12 == $check;
155
            }
156
            return $c12 == 0;
157
        } catch (NegativeNumberException $e) {
158
            return false;
159
        }
160
    }
161
162
    private function isValidDate(string $tin)
163
    {
164
        $year = intval(StringUtil::substring($tin, 0, 2));
165
        $month = intval(StringUtil::substring($tin, 2, 4));
166
        $day = intval(StringUtil::substring($tin, 4, 6));
167
        return DateUtil::validate(1900 + $year, $month, $day) || DateUtil::validate(2000 + $year, $month, $day);
168
    }
169
170
    private function isValidDate2(string $tin)
171
    {
172
        $year = intval(StringUtil::substring($tin, 0, 2));
173
        $month = intval(StringUtil::substring($tin, 2, 4));
174
        $day = intval(StringUtil::substring($tin, 4, 6));
175
        return DateUtil::validate(1900 + $year, $month, $day - 60) || DateUtil::validate(2000 + $year, $month, $day - 60);
176
    }
177
178
    private function isValidDate3(string $tin)
179
    {
180
        $year = intval(StringUtil::substring($tin, 0, 4));
181
        $month = intval(StringUtil::substring($tin, 4, 6));
182
        $day = intval(StringUtil::substring($tin, 6, 8));
183
        return DateUtil::validate($year, $month, $day);
184
    }
185
186
    private function isValidDate4(string $tin)
187
    {
188
        $year = intval(StringUtil::substring($tin, 0, 4));
189
        $month = intval(StringUtil::substring($tin, 4, 6));
190
        $day = intval(StringUtil::substring($tin, 6, 8));
191
        return DateUtil::validate($year, $month, $day - 60);
192
    }
193
}
194