Completed
Pull Request — master (#20)
by Davide
01:27
created

Calculator::replaceOmocodiaSection()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

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