Passed
Push — master ( d55cf9...86fc82 )
by Antonio Oertel
26s
created

Voter::calculateFirstDigit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.6666
cc 1
eloc 6
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Brazanation\Documents;
4
5
use Brazanation\Documents\Exception\InvalidDocument as InvalidDocumentException;
6
7
final class Voter implements DocumentInterface
8
{
9
    const LENGTH = 12;
10
11
    const LABEL = 'Voter';
12
13
    private $voter;
14
15
    private $section;
16
17
    private $zone;
18
19
    /**
20
     * Voter constructor.
21
     *
22
     * @param string $number
23
     * @param string $section [optional]
24
     * @param string $zone    [optional]
25
     */
26 13
    public function __construct($number, $section = null, $zone = null)
27
    {
28 13
        $this->validate($number);
29 7
        $this->voter = $number;
30 7
        $this->section = str_pad($section, 4, '0', STR_PAD_LEFT);
31 7
        $this->zone = str_pad($zone, 3, '0', STR_PAD_LEFT);
32 7
    }
33
34
    /**
35
     * @return string
36
     */
37
    public function getSection()
38
    {
39
        return $this->section;
40
    }
41
42
    /**
43
     * @return string
44
     */
45
    public function getZone()
46
    {
47
        return $this->zone;
48
    }
49
50
    /**
51
     * @return string
52
     */
53 6
    public function __toString()
54
    {
55 6
        return $this->voter;
56
    }
57
58
    /**
59
     * @return string
60
     */
61 1
    public function format()
62
    {
63 1
        return preg_replace('/[^\d]/', '', $this->voter);
64
    }
65
66
    /**
67
     * @param string $number
68
     *
69
     * @throws InvalidDocumentException
70
     */
71 13
    private function validate($number)
72
    {
73 13
        if (empty($number)) {
74 3
            throw InvalidDocumentException::notEmpty(self::LABEL);
75
        }
76 10
        if (!$this->isValid($number)) {
77 3
            throw InvalidDocumentException::isNotValid(self::LABEL, $number);
78
        }
79 7
    }
80
81
    /**
82
     * @param string $number
83
     *
84
     * @return bool
85
     */
86 10
    private function isValid($number)
87
    {
88 10
        if (strlen($number) != self::LENGTH) {
89 1
            return false;
90
        }
91
92 9
        if (preg_match("/^{$number[0]}{" . self::LENGTH . '}$/', $number)) {
93
            return false;
94
        }
95
96 9
        $baseNumber = substr($number, 0, -2);
97 9
        $firstDigit = $this->calculateFirstDigit($baseNumber);
98 9
        $secondDigit = $this->calculateSecondDigit("{$baseNumber}{$firstDigit}");
99
100 9
        return "{$firstDigit}{$secondDigit}" === substr($number, -2);
101
    }
102
103
    /**
104
     * @param string $number
105
     *
106
     * @return string
107
     */
108 9
    private function calculateFirstDigit($number)
109
    {
110 9
        $calculator = new DigitCalculator(substr($number, 0, -2));
111 9
        $calculator->withMultipliers([9, 8, 7, 6, 5, 4, 3, 2]);
112 9
        $calculator->withModule(DigitCalculator::MODULE_11);
113 9
        $digit = $calculator->calculate();
114
115 9
        return "{$digit}";
116
    }
117
118
    /**
119
     * @param string $number
120
     *
121
     * @return string
122
     */
123 9
    private function calculateSecondDigit($number)
124
    {
125 9
        $calculator = new DigitCalculator(substr($number, -3));
126 9
        $calculator->withMultipliers([9, 8, 7]);
127 9
        $calculator->withModule(DigitCalculator::MODULE_11);
128 9
        $digit = $calculator->calculate();
129
130 9
        return "{$digit}";
131
    }
132
}
133