Completed
Pull Request — master (#12)
by Antonio
01:42
created

Calculator::calculateCheckDigit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 1
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 22
    public function __construct(Subject $subject, $properties = array())
27
    {
28 22
        $this->subject = $subject;
29
30 22
        if (array_key_exists('omocodiaLevel', $properties)) {
31 20
            $this->omocodiaLevel = $properties['omocodiaLevel'];
32
        }
33 22
    }
34
35
    /**
36
     * Calculate the code fiscale.
37
     *
38
     * @returns Returns the complete codice fiscale.
39
     */
40 22
    public function calculate()
41
    {
42 22
        $temporaryCodiceFiscale = $this->calculateSurname().$this->calculateName().
43 22
               $this->calculateBirthDateAndGender().$this->calculateBelfioreCode();
44 22
        $temporaryCodiceFiscale = $this->calculateOmocodia($temporaryCodiceFiscale);
45
46 22
        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 3
    public function calculateAllPossibilities()
55
    {
56 3
        $allPossibilities = array();
57 3
        for ($i = 0; $i < 8; ++$i) {
58 3
            $this->omocodiaLevel = $i;
59 3
            $allPossibilities[] = $this->calculate();
60
        }
61
62 3
        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 22
    private function calculateSurname()
71
    {
72 22
        $consonants = str_replace($this->vowels, '', strtoupper($this->subject->getSurname()));
73 22
        $consonants = $this->cleanString($consonants);
74 22
        if (strlen($consonants) > 2) {
75 18
            $result = substr($consonants, 0, 3);
76
        } else {
77 4
            $result = $this->calculateSmallString($consonants, $this->subject->getSurname());
78
        }
79
80 22
        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 22
    private function calculateName()
89
    {
90 22
        $consonants = str_replace($this->vowels, '', strtoupper($this->subject->getName()));
91 22
        $consonants = $this->cleanString($consonants);
92 22
        if (strlen($consonants) > 3) {
93 6
            $result = $consonants[0].$consonants[2].$consonants[3];
94 16
        } elseif (strlen($consonants) == 3) {
95 1
            $result = $consonants;
96
        } else {
97 15
            $result = $this->calculateSmallString($consonants, $this->subject->getName());
98
        }
99
100 22
        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 15
    private function calculateSmallString($consonants, $string)
111
    {
112 15
        $string = $this->cleanString($string);
113 15
        $vowels = str_replace(str_split($consonants), '', strtoupper($string));
114 15
        $result = substr($consonants.$vowels.'XXX', 0, 3);
115
116 15
        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 22
    private function calculateBirthDateAndGender()
125
    {
126 22
        $year = $this->subject->getBirthDate()->format('y');
127 22
        $month = $this->months[$this->subject->getBirthDate()->format('n')];
128 22
        $day = $this->subject->getBirthDate()->format('d');
129 22
        if (strtoupper($this->subject->getGender()) == self::CHR_WOMEN) {
130 2
            $day += 40;
131
        }
132
133 22
        return $year.$month.$day;
134
    }
135
136
    /**
137
     * Calculate the Belfiore code.
138
     *
139
     * @returns Returns the Belfiore code.
140
     */
141 22
    private function calculateBelfioreCode()
142
    {
143 22
        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 22
    private function calculateOmocodia($temporaryCodiceFiscale)
153
    {
154 22
        if ($this->omocodiaLevel > 0) {
155 7
            $omocodiaLevelApplied = 0;
156 7
            for ($i = strlen($temporaryCodiceFiscale) - 1; $i > 0; --$i) {
157 7
                $k = $temporaryCodiceFiscale{$i};
158 7
                if ($omocodiaLevelApplied < $this->omocodiaLevel && is_numeric($k)) {
159 7
                    $newChar = $this->omocodiaCodes[$k];
160 7
                    $temporaryCodiceFiscale{$i}
161
                    = $newChar;
162 7
                    ++$omocodiaLevelApplied;
163
                }
164
            }
165
        }
166
167 22
        return $temporaryCodiceFiscale;
168
    }
169
170
    /**
171
     * Clean the string removing some characters.
172
     *
173
     * @param $string The string to clean.
174
     * @returns Returns a clean string.
175
     */
176 22
    private function cleanString($string)
177
    {
178 22
        return preg_replace('/[\s\'"`]+/', '', $string);
179
    }
180
}
181