Completed
Push — master ( 59c50d...1e8f66 )
by Davide
02:13
created

src/DavidePastore/CodiceFiscale/Calculator.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 = 0;
238 17
		$sumOdd = 0;
239 17 View Code Duplication
		for ($i = 0; $i < 15; $i = $i + 2)
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
240
		{
241 17
			$k = $temporaryCodiceFiscale{$i};
242 17
			$sumOdd = $sumOdd + $this->odd[$k];
243 17
		}
244
	
245 17 View Code Duplication
		for ($i = 1; $i < 15; $i = $i + 2)
0 ignored issues
show
This code seems to be duplicated across your project.

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.

Loading history...
246
		{
247 17
			$k = $temporaryCodiceFiscale{$i};
248 17
			$sumEven = $sumEven + $this->even[$k];
249 17
		}
250
        
251 17
		return chr(($sumOdd + $sumEven) % 26 + 65);
252
    }
253
    
254
    /**
255
     * Calculate the omocodia case (additional translation).
256
     * @param $temporaryCodiceFiscale The first part of the codice fiscale.
257
     * @returns Returns the new codice fiscale.
258
     */
259 17
    private function calculateOmocodia($temporaryCodiceFiscale){
260 17
        if($this->omocodiaLevel > 0){
261 7
            $omocodiaLevelApplied = 0;
262 7
            for($i = strlen($temporaryCodiceFiscale) - 1; $i > 0; $i--){
263 7
                $k = $temporaryCodiceFiscale{$i};
264 7
                if($omocodiaLevelApplied < $this->omocodiaLevel && is_numeric($k)){
265 7
                    $newChar = $this->omocodiaCodes[$k];
266 7
                    $temporaryCodiceFiscale{$i} = $newChar;
267 7
                    $omocodiaLevelApplied++;
268 7
                }
269 7
            }
270 7
        }
271 17
        return $temporaryCodiceFiscale;
272
    }
273
}
274