1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace DavidePastore\CodiceFiscale; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Codice Fiscale calculator. |
7
|
|
|
* @author davidepastore |
8
|
|
|
* |
9
|
|
|
*/ |
10
|
|
|
class Calculator |
11
|
|
|
{ |
12
|
|
|
|
13
|
|
|
private $subject; |
14
|
|
|
private $omocodiaLevel = 0; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Array of available vowels. |
18
|
|
|
*/ |
19
|
|
|
private $vowels = array('A', 'E', 'I', 'O', 'U'); |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Array of all available months. |
23
|
|
|
*/ |
24
|
|
|
private $months = array( |
25
|
|
|
'1' => 'A', |
26
|
|
|
'2' => 'B', |
27
|
|
|
'3' => 'C', |
28
|
|
|
'4' => 'D', |
29
|
|
|
'5' => 'E', |
30
|
|
|
'6' => 'H', |
31
|
|
|
'7' => 'L', |
32
|
|
|
'8' => 'M', |
33
|
|
|
'9' => 'P', |
34
|
|
|
'10' => 'R', |
35
|
|
|
'11' => 'S', |
36
|
|
|
'12' => 'T' |
37
|
|
|
); |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Array of all avaialable odd characters. |
41
|
|
|
*/ |
42
|
|
|
private $odd = array( |
43
|
|
|
'0' => 1, |
44
|
|
|
'1' => 0, |
45
|
|
|
'2' => 5, |
46
|
|
|
'3' => 7, |
47
|
|
|
'4' => 9, |
48
|
|
|
'5' => 13, |
49
|
|
|
'6' => 15, |
50
|
|
|
'7' => 17, |
51
|
|
|
'8' => 19, |
52
|
|
|
'9' => 21, |
53
|
|
|
'A' => 1, |
54
|
|
|
'B' => 0, |
55
|
|
|
'C' => 5, |
56
|
|
|
'D' => 7, |
57
|
|
|
'E' => 9, |
58
|
|
|
'F' => 13, |
59
|
|
|
'G' => 15, |
60
|
|
|
'H' => 17, |
61
|
|
|
'I' => 19, |
62
|
|
|
'J' => 21, |
63
|
|
|
'K' => 2, |
64
|
|
|
'L' => 4, |
65
|
|
|
'M' => 18, |
66
|
|
|
'N' => 20, |
67
|
|
|
'O' => 11, |
68
|
|
|
'P' => 3, |
69
|
|
|
'Q' => 6, |
70
|
|
|
'R' => 8, |
71
|
|
|
'S' => 12, |
72
|
|
|
'T' => 14, |
73
|
|
|
'U' => 16, |
74
|
|
|
'V' => 10, |
75
|
|
|
'W' => 22, |
76
|
|
|
'X' => 25, |
77
|
|
|
'Y' => 24, |
78
|
|
|
'Z' => 23 |
79
|
|
|
); |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Array of all avaialable even characters. |
83
|
|
|
*/ |
84
|
|
|
private $even = array( |
85
|
|
|
'0' => 0, |
86
|
|
|
'1' => 1, |
87
|
|
|
'2' => 2, |
88
|
|
|
'3' => 3, |
89
|
|
|
'4' => 4, |
90
|
|
|
'5' => 5, |
91
|
|
|
'6' => 6, |
92
|
|
|
'7' => 7, |
93
|
|
|
'8' => 8, |
94
|
|
|
'9' => 9, |
95
|
|
|
'A' => 0, |
96
|
|
|
'B' => 1, |
97
|
|
|
'C' => 2, |
98
|
|
|
'D' => 3, |
99
|
|
|
'E' => 4, |
100
|
|
|
'F' => 5, |
101
|
|
|
'G' => 6, |
102
|
|
|
'H' => 7, |
103
|
|
|
'I' => 8, |
104
|
|
|
'J' => 9, |
105
|
|
|
'K' => 10, |
106
|
|
|
'L' => 11, |
107
|
|
|
'M' => 12, |
108
|
|
|
'N' => 13, |
109
|
|
|
'O' => 14, |
110
|
|
|
'P' => 15, |
111
|
|
|
'Q' => 16, |
112
|
|
|
'R' => 17, |
113
|
|
|
'S' => 18, |
114
|
|
|
'T' => 19, |
115
|
|
|
'U' => 20, |
116
|
|
|
'V' => 21, |
117
|
|
|
'W' => 22, |
118
|
|
|
'X' => 23, |
119
|
|
|
'Y' => 24, |
120
|
|
|
'Z' => 25 |
121
|
|
|
); |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Array of all avaialable omocodia characters. |
125
|
|
|
*/ |
126
|
|
|
private $omocodiaCodes = array( |
127
|
|
|
'0' => 'L', |
128
|
|
|
'1' => 'M', |
129
|
|
|
'2' => 'N', |
130
|
|
|
'3' => 'P', |
131
|
|
|
'4' => 'Q', |
132
|
|
|
'5' => 'R', |
133
|
|
|
'6' => 'S', |
134
|
|
|
'7' => 'T', |
135
|
|
|
'8' => 'U', |
136
|
|
|
'9' => 'V' |
137
|
|
|
); |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* Create a Codice Fiscale instance. |
141
|
|
|
* @param Subject $subject The subject that will have the codice fiscale. |
142
|
|
|
* @param $properties An array with additional properties. |
143
|
|
|
*/ |
144
|
17 |
|
public function __construct(Subject $subject, $properties = array()){ |
145
|
17 |
|
$this->subject = $subject; |
146
|
|
|
|
147
|
17 |
|
if (array_key_exists('omocodiaLevel', $properties)) { |
148
|
15 |
|
$this->omocodiaLevel = $properties['omocodiaLevel']; |
149
|
15 |
|
} |
150
|
17 |
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Calculate the code fiscale. |
154
|
|
|
* @returns Returns the complete codice fiscale. |
155
|
|
|
*/ |
156
|
17 |
|
public function calculate(){ |
157
|
17 |
|
$temporaryCodiceFiscale = $this->calculateSurname() . $this->calculateName() . |
158
|
17 |
|
$this->calculateBirthDateAndGender() . $this->calculateBelfioreCode(); |
159
|
17 |
|
$temporaryCodiceFiscale = $this->calculateOmocodia($temporaryCodiceFiscale); |
160
|
17 |
|
return $temporaryCodiceFiscale . $this->calculateCheckDigit($temporaryCodiceFiscale); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
/** |
164
|
|
|
* Calculate all possibilities for the code fiscale. |
165
|
|
|
* @returns Returns the complete codice fiscale. |
166
|
|
|
*/ |
167
|
3 |
|
public function calculateAllPossibilities(){ |
168
|
3 |
|
$allPossibilities = array(); |
169
|
3 |
|
for($i = 0; $i < 8; $i++){ |
170
|
3 |
|
$this->omocodiaLevel = $i; |
171
|
3 |
|
$allPossibilities[] = $this->calculate(); |
172
|
3 |
|
} |
173
|
3 |
|
return $allPossibilities; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Calculate the surname part of the codice fiscale. |
179
|
|
|
* @returns Returns the surname part of the codice fiscale. |
180
|
|
|
*/ |
181
|
17 |
|
private function calculateSurname(){ |
182
|
17 |
|
$consonants = str_replace($this->vowels, '', $this->subject->getSurname()); |
183
|
17 |
View Code Duplication |
if(strlen($consonants) > 2){ |
|
|
|
|
184
|
14 |
|
$result = substr($consonants, 0, 3); |
185
|
14 |
|
} else { |
186
|
3 |
|
$vowels = str_replace(str_split($consonants), '', $this->subject->getSurname()); |
187
|
3 |
|
$result = substr($consonants . $vowels . 'XXX', 0, 3); |
188
|
|
|
} |
189
|
17 |
|
return $result; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* Calculate the name part of the codice fiscale. |
194
|
|
|
* @returns Returns the name part of the codice fiscale. |
195
|
|
|
*/ |
196
|
17 |
|
private function calculateName(){ |
197
|
17 |
|
$consonants = str_replace($this->vowels, '', $this->subject->getName()); |
198
|
17 |
|
if(strlen($consonants) > 3){ |
199
|
5 |
|
$result = $consonants[0] . $consonants[2] . $consonants[3]; |
200
|
17 |
View Code Duplication |
} else if(strlen($consonants) == 3){ |
|
|
|
|
201
|
|
|
$result = join($consonants); |
202
|
|
|
} else{ |
203
|
12 |
|
$vowels = str_replace(str_split($consonants), '', $this->subject->getName()); |
204
|
12 |
|
$result = substr($consonants . $vowels . 'XXX', 0, 3); |
205
|
|
|
} |
206
|
17 |
|
return $result; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Calculate the birth date and the gender. |
211
|
|
|
* @returns Returns the birth date and gender part of the codice fiscale. |
212
|
|
|
*/ |
213
|
17 |
|
private function calculateBirthDateAndGender(){ |
214
|
17 |
|
$year = $this->subject->getBirthDate()->format('y'); |
215
|
17 |
|
$month = $this->months[$this->subject->getBirthDate()->format('n')]; |
216
|
17 |
|
$day = $this->subject->getBirthDate()->format('d'); |
217
|
17 |
|
if($this->subject->getGender() == "F"){ |
218
|
1 |
|
$day += 40; |
219
|
1 |
|
} |
220
|
17 |
|
return $year . $month . $day; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Calculate the Belfiore code. |
225
|
|
|
* @returns Returns the Belfiore code. |
226
|
|
|
*/ |
227
|
17 |
|
private function calculateBelfioreCode(){ |
228
|
17 |
|
return $this->subject->getBelfioreCode(); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Calculate the check digit. |
233
|
|
|
* @param $temporaryCodiceFiscale The first part of the codice fiscale. |
234
|
|
|
* @returns Returns the check digit part of the codice fiscale. |
235
|
|
|
*/ |
236
|
17 |
|
private function calculateCheckDigit($temporaryCodiceFiscale){ |
237
|
17 |
|
$sumEven = $this->calculateSumByDictionary($temporaryCodiceFiscale, $this->even, 1); |
238
|
17 |
|
$sumOdd = $this->calculateSumByDictionary($temporaryCodiceFiscale, $this->odd, 0); |
239
|
17 |
|
return chr(($sumOdd + $sumEven) % 26 + 65); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Calculate the sum by the given dictionary for the given temporary codice fiscale. |
244
|
|
|
* @param $temporaryCodiceFiscale The temporary codice fiscale. |
245
|
|
|
* @param $dictionaryArray The dictionary array. |
246
|
|
|
* @param $i The start index value. |
247
|
|
|
* @returns Returns the sum by the given dictionary for the given temporary codice fiscale. |
248
|
|
|
* |
249
|
|
|
*/ |
250
|
17 |
|
private function calculateSumByDictionary($temporaryCodiceFiscale, $dictionaryArray, $i){ |
251
|
17 |
|
$sum = 0; |
252
|
17 |
|
for (; $i < 15; $i = $i + 2) |
253
|
|
|
{ |
254
|
17 |
|
$k = $temporaryCodiceFiscale{$i}; |
255
|
17 |
|
$sum = $sum + $dictionaryArray[$k]; |
256
|
17 |
|
} |
257
|
17 |
|
return $sum; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Calculate the omocodia case (additional translation). |
262
|
|
|
* @param $temporaryCodiceFiscale The first part of the codice fiscale. |
263
|
|
|
* @returns Returns the new codice fiscale. |
264
|
|
|
*/ |
265
|
17 |
|
private function calculateOmocodia($temporaryCodiceFiscale){ |
266
|
17 |
|
if($this->omocodiaLevel > 0){ |
267
|
7 |
|
$omocodiaLevelApplied = 0; |
268
|
7 |
|
for($i = strlen($temporaryCodiceFiscale) - 1; $i > 0; $i--){ |
269
|
7 |
|
$k = $temporaryCodiceFiscale{$i}; |
270
|
7 |
|
if($omocodiaLevelApplied < $this->omocodiaLevel && is_numeric($k)){ |
271
|
7 |
|
$newChar = $this->omocodiaCodes[$k]; |
272
|
7 |
|
$temporaryCodiceFiscale{$i} = $newChar; |
273
|
7 |
|
$omocodiaLevelApplied++; |
274
|
7 |
|
} |
275
|
7 |
|
} |
276
|
7 |
|
} |
277
|
17 |
|
return $temporaryCodiceFiscale; |
278
|
|
|
} |
279
|
|
|
} |
280
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.