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