Completed
Push — master ( fa5c54...e47d70 )
by Davide
04:12
created

Calculator::calculateOmocodia()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 58

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 46
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 58
ccs 46
cts 46
cp 1
rs 8.9163
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace CodiceFiscale;
4
5
use Normalizer;
6
7
/**
8
 * Codice Fiscale calculator.
9
 *
10
 * @author davidepastore
11
 */
12
class Calculator extends AbstractCalculator
13
{
14
    private $subject;
15
    private $omocodiaLevel = 0;
16
17
    /**
18
     * Array of available vowels.
19
     */
20
    private $vowels = array('A', 'E', 'I', 'O', 'U');
21
22
    /**
23
     * Create a Codice Fiscale instance.
24
     *
25
     * @param Subject $subject The subject that will have the codice fiscale.
26
     * @param array $properties An array with additional properties.
27
     */
28 25
    public function __construct(Subject $subject, $properties = array())
29
    {
30 25
        $this->subject = $subject;
31
32 25
        if (array_key_exists('omocodiaLevel', $properties)) {
33 23
            $this->omocodiaLevel = $properties['omocodiaLevel'];
34
        }
35 25
    }
36
37
    /**
38
     * Calculate the code fiscale.
39
     *
40
     * @returns string The complete codice fiscale.
41
     */
42 25
    public function calculate()
43
    {
44 25
        $temporaryCodiceFiscale = $this->calculateSurname() . $this->calculateName() .
45 25
                $this->calculateBirthDateAndGender() . $this->calculateBelfioreCode();
46 25
        $temporaryCodiceFiscale = $this->calculateOmocodia($temporaryCodiceFiscale);
47
48 25
        return $temporaryCodiceFiscale . $this->calculateCheckDigit($temporaryCodiceFiscale);
49
    }
50
51
    /**
52
     * Calculate all possibilities for the code fiscale.
53
     *
54
     * @return array The list of all possibilities for the code fiscale.
55
     */
56 5
    public function calculateAllPossibilities()
57
    {
58 5
        $allPossibilities = array();
59 5
        for ($i = 0; $i < 128; ++$i) {
60 5
            $this->omocodiaLevel = $i;
61 5
            $allPossibilities[] = $this->calculate();
62
        }
63
64 5
        return $allPossibilities;
65
    }
66
67
    /**
68
     * Calculate the surname part of the codice fiscale.
69
     *
70
     * @return string The surname part of the codice fiscale.
71
     */
72 25
    private function calculateSurname()
73
    {
74 25
        $surname = $this->cleanString($this->subject->getSurname());
75 25
        $consonants = str_replace($this->vowels, '', strtoupper($surname));
76 25
        if (strlen($consonants) > 2) {
77 19
            $result = substr($consonants, 0, 3);
78
        } else {
79 6
            $result = $this->calculateSmallString($consonants, $surname);
80
        }
81
82 25
        return $result;
83
    }
84
85
    /**
86
     * Calculate the name part of the codice fiscale.
87
     *
88
     * @return string The name part of the codice fiscale.
89
     */
90 25
    private function calculateName()
91
    {
92 25
        $name = $this->cleanString($this->subject->getName());
93 25
        $consonants = str_replace($this->vowels, '', strtoupper($name));
94 25
        if (strlen($consonants) > 3) {
95 8
            $result = $consonants[0] . $consonants[2] . $consonants[3];
96 17
        } elseif (strlen($consonants) == 3) {
97 1
            $result = $consonants;
98
        } else {
99 16
            $result = $this->calculateSmallString($consonants, $name);
100
        }
101
102 25
        return $result;
103
    }
104
105
    /**
106
     * Calculate small string for the given parameters (used by name and surname).
107
     *
108
     * @param string $consonants   A consonants string.
109
     * @param string $string  The small string.
110
     * @return string The calculated result for the small string.
111
     */
112 18
    private function calculateSmallString($consonants, $string)
113
    {
114 18
        $string = $this->cleanString($string);
115 18
        $vowels = str_replace(str_split($consonants), '', strtoupper($string));
116 18
        $result = substr($consonants . $vowels . 'XXX', 0, 3);
117
118 18
        return $result;
119
    }
120
121
    /**
122
     * Calculate the birth date and the gender.
123
     *
124
     * @returns string The birth date and gender part of the codice fiscale.
125
     */
126 25
    private function calculateBirthDateAndGender()
127
    {
128 25
        $year = $this->subject->getBirthDate()->format('y');
129 25
        $month = $this->months[$this->subject->getBirthDate()->format('n')];
130 25
        $day = $this->subject->getBirthDate()->format('d');
131 25
        if (strtoupper($this->subject->getGender()) == self::CHR_WOMEN) {
132 4
            $day += 40;
133
        }
134
135 25
        return $year . $month . $day;
136
    }
137
138
    /**
139
     * Calculate the Belfiore code.
140
     *
141
     * @return string The Belfiore code.
142
     */
143 25
    private function calculateBelfioreCode()
144
    {
145 25
        return strtoupper($this->subject->getBelfioreCode());
146
    }
147
148
    /**
149
     * Calculate the omocodia case (additional translation).
150
     *
151
     * @param $temporaryCodiceFiscale string The first part of the codice fiscale.
152
     * @return string
153
     */
154 25
    private function calculateOmocodia($temporaryCodiceFiscale)
155
    {
156 25
        if ($this->omocodiaLevel > 0) {
157 9
            if ($this->omocodiaLevel) {
158 9
                $temporaryCodiceFiscale = $this->replaceOmocodiaSection(
159 9
                    2,
160 9
                    $temporaryCodiceFiscale,
161 9
                    1,
162 9
                    1,
163 9
                    $this->omocodiaPositions[0]
164
                );
165 9
                $temporaryCodiceFiscale = $this->replaceOmocodiaSection(
166 9
                    4,
167 9
                    $temporaryCodiceFiscale,
168 9
                    2,
169 9
                    3,
170 9
                    $this->omocodiaPositions[1]
171
                );
172 9
                $temporaryCodiceFiscale = $this->replaceOmocodiaSection(
173 9
                    8,
174 9
                    $temporaryCodiceFiscale,
175 9
                    4,
176 9
                    7,
177 9
                    $this->omocodiaPositions[2]
178
                );
179 9
                $temporaryCodiceFiscale = $this->replaceOmocodiaSection(
180 9
                    16,
181 9
                    $temporaryCodiceFiscale,
182 9
                    8,
183 9
                    15,
184 9
                    $this->omocodiaPositions[3]
185
                );
186 9
                $temporaryCodiceFiscale = $this->replaceOmocodiaSection(
187 9
                    32,
188 9
                    $temporaryCodiceFiscale,
189 9
                    16,
190 9
                    31,
191 9
                    $this->omocodiaPositions[4]
192
                );
193 9
                $temporaryCodiceFiscale = $this->replaceOmocodiaSection(
194 9
                    64,
195 9
                    $temporaryCodiceFiscale,
196 9
                    32,
197 9
                    63,
198 9
                    $this->omocodiaPositions[5]
199
                );
200 9
                $temporaryCodiceFiscale = $this->replaceOmocodiaSection(
201 9
                    128,
202 9
                    $temporaryCodiceFiscale,
203 9
                    64,
204 9
                    127,
205 9
                    $this->omocodiaPositions[6]
206
                );
207
            }
208
        }
209
210 25
        return $temporaryCodiceFiscale;
211
    }
212
213
    /**
214
     * Replace a section of the omocodia.
215
     *
216
     * @param $divider int The divider.
217
     * @param $temporaryCodiceFiscale string The first part of the codice fiscale on which make the substitutions.
218
     * @param $startingIndex int The starting index.
219
     * @param $endingIndex int The ending index.
220
     * @param $characterIndex int The index to use to make the substitutions on the $temporaryCodiceFiscale.
221
     * @return string The temporary codice fiscale with the substitutions made.
222
     */
223 9
    private function replaceOmocodiaSection(
224
        $divider,
225
        $temporaryCodiceFiscale,
226
        $startingIndex,
227
        $endingIndex,
228
        $characterIndex
229
    ) {
230 9
        if ($this->omocodiaLevel % $divider >= $startingIndex && $this->omocodiaLevel % $divider <= $endingIndex) {
231 9
            $k = $temporaryCodiceFiscale[$characterIndex];
232 9
            $newChar = $this->omocodiaCodes[$k];
233 9
            $temporaryCodiceFiscale[$characterIndex] = $newChar;
234
        }
235 9
        return $temporaryCodiceFiscale;
236
    }
237
238
    /**
239
     * @param $string string The string to clean.
240
     * @return string Cleaned string
241
     */
242 25
    private function cleanString($string)
243
    {
244 25
        return preg_replace(array('/\pM*/u', '/[\s\'"`]+/'), '', Normalizer::normalize($string, Normalizer::FORM_D));
245
    }
246
}
247