NaturalizationRecord::validateUsingAlternativeAlgorithm()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.3332

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 6
cts 9
cp 0.6667
rs 9.6666
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3.3332
1
<?php
2
3
/*
4
 * @copyright 2018 Hilmi Erdem KEREN
5
 * @license MIT
6
 */
7
8
namespace Erdemkeren\Validators\TrNatIdNumValidator;
9
10
/**
11
 * Class NaturalizationRecord.
12
 */
13
final class NaturalizationRecord
14
{
15
    /**
16
     * The turkish-letter filter pattern.
17
     *
18
     * @var string
19
     */
20
    private static $letterFilterPattern = '/[^a-zA-Z\sŞşİıĞğÜüÖöÇçÂâîîÛû.]/';
21
22
    /**
23
     * The number filter pattern.
24
     *
25
     * @var string
26
     */
27
    private static $numberFilterPattern = '/[^0-9]/';
28
29
    /**
30
     * The valid national identification number pattern.
31
     *
32
     * @var string
33
     */
34
    private static $trNationalIdNumberPattern = '/^[1-9]{1}[0-9]{9}[0,2,4,6,8]{1}$/';
35
36
    /**
37
     * The national identification number.
38
     *
39
     * @var string
40
     */
41
    private $natIdNum;
42
43
    /**
44
     * The first name.
45
     *
46
     * @var string
47
     */
48
    private $firstName;
49
50
    /**
51
     * The last name.
52
     *
53
     * @var string
54
     */
55
    private $lastName;
56
57
    /**
58
     * The birth year.
59
     *
60
     * @var int
61
     */
62
    private $birthYear;
63
64
    /**
65
     * NaturalizationRecord constructor.
66
     *
67
     * @param string $natIdNum
68
     * @param string $firstName
69
     * @param string $lastName
70
     * @param int    $birthYear
71
     */
72 5
    public function __construct(string $natIdNum, string $firstName, string $lastName, int $birthYear)
73
    {
74 5
        $this->lastName = self::tr_strtoupper(preg_replace(self::$letterFilterPattern, '', $lastName));
75 5
        $this->firstName = self::tr_strtoupper(preg_replace(self::$letterFilterPattern, '', $firstName));
76 5
        $this->birthYear = (int) preg_replace(self::$numberFilterPattern, '', (string) $birthYear);
77 5
        $this->natIdNum = preg_replace(self::$numberFilterPattern, '', $natIdNum);
78
79 5
        $natIdNum = $this->natIdNum();
80 5
        $isAlgorithmValid = false;
81 5
        $isPatternValid = $this->validatePattern($natIdNum);
82
83 5
        if ($isPatternValid) {
84 4
            $isAlgorithmValid = $this->validateAlgorithm($natIdNum) || $this->validateUsingAlternativeAlgorithm($natIdNum);
85
        }
86
87 5
        if (! ($isPatternValid && $isAlgorithmValid)) {
88 3
            $this->throwValidationException('The given national identification number is invalid.');
89
        }
90 2
    }
91
92
    /**
93
     * Get the national identification number.
94
     *
95
     * @return string
96
     */
97 5
    public function natIdNum(): string
98
    {
99 5
        return $this->natIdNum;
100
    }
101
102
    /**
103
     * Get the first name.
104
     *
105
     * @return string
106
     */
107 1
    public function firstName(): string
108
    {
109 1
        return $this->firstName;
110
    }
111
112
    /**
113
     * Get the last name.
114
     *
115
     * @return string
116
     */
117 1
    public function lastName(): string
118
    {
119 1
        return $this->lastName;
120
    }
121
122
    /**
123
     * Get the birth year.
124
     *
125
     * @return int
126
     */
127 1
    public function birthYear(): int
128
    {
129 1
        return $this->birthYear;
130
    }
131
132
    /**
133
     * Validate the pattern of the given national identification number.
134
     *
135
     * @param string $natIdNum
136
     *
137
     * @return bool
138
     */
139 5
    private function validatePattern(string $natIdNum): bool
140
    {
141 5
        return preg_match(self::$trNationalIdNumberPattern, $natIdNum) ? true : false;
142
    }
143
144
    /**
145
     * Validate the given national identification number algorithmically.
146
     *
147
     * @param string $id
148
     *
149
     * @return bool
150
     */
151 4
    private function validateAlgorithm(string $id): bool
152
    {
153 4
        $sumOfOdds = $id[0] + $id[2] + $id[4] + $id[6] + $id[8];
154 4
        $sumOfEvens = $id[1] + $id[3] + $id[5] + $id[7];
155
156 4
        $controlDigitOne = (int) $id[9];
157 4
        $controlDigitTwo = (int) $id[10];
158 4
        $testVariableOne = (int) ($sumOfOdds * 7 - $sumOfEvens) % 10;
159 4
        $testVariableTwo = (int) ($sumOfOdds + $sumOfEvens + $controlDigitOne) % 10;
160
161 4
        if (($testVariableOne !== $controlDigitOne) || ($testVariableTwo !== $controlDigitTwo)) {
162 2
            return false;
163
        }
164
165 2
        return true;
166
    }
167
168
    /**
169
     * Validate the given national identification using the alternative algorithm.
170
     *
171
     * @param string $id
172
     *
173
     * @return bool
174
     */
175 2
    private function validateUsingAlternativeAlgorithm(string $id): bool
176
    {
177 2
        $sumOfOdds = $id[0] + $id[2] + $id[4] + $id[6] + $id[8];
178
        $sumOfFirstTenDigits = (
179 2
            $id[0] + $id[1] + $id[2] + $id[3] + $id[4] +
180 2
            $id[5] + $id[6] + $id[7] + $id[8] + $id[9]
181
        );
182
183 2
        if ($sumOfFirstTenDigits % 10 !== (int) $id[10]) {
184 2
            return false;
185
        }
186
187
        if (($sumOfOdds * 8) % 10 !== (int) $id[10]) {
188
            return false;
189
        }
190
191
        return true;
192
    }
193
194
    /**
195
     * Throws an invalid Turkish National Identification Number exception with the given message.
196
     *
197
     * @param string $message
198
     */
199 3
    private function throwValidationException(string $message): void
200
    {
201 3
        throw new InvalidTurkishNationalIdentificationNumberException($message);
202
    }
203
204
    /**
205
     * The turkish str to upper function which works right.
206
     *
207
     * @param string $str
208
     *
209
     * @return string
210
     */
211 5
    private static function tr_strtoupper(string $str): string
212
    {
213 5
        return strtoupper(str_replace(['ç', 'i', 'ı', 'ğ', 'ö', 'ş', 'ü', 'â', 'î', 'û'], ['Ç', 'İ', 'I', 'Ğ', 'Ö', 'Ş', 'Ü', 'Â', 'Î', 'Û'], $str));
214
    }
215
}
216