Completed
Push — master ( 396474...e3213f )
by Antonio Oertel
04:21 queued 01:33
created

Cnh::calculateSecondDigit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 10
ccs 7
cts 7
cp 1
rs 9.4285
cc 1
eloc 7
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Brazanation\Documents;
4
5
use Brazanation\Documents\Exception\InvalidDocument as InvalidArgumentException;
6
7
final class Cnh implements DocumentInterface
8
{
9
    const LENGTH = 11;
10
11
    const LABEL = 'CNH';
12
13
    const REGEX = '/^([\d]{3})([\d]{3})([\d]{4})([\d]{1})$/';
14
15
    /**
16
     * @var string
17
     */
18
    private $cnh;
19
20
    /**
21
     * Cnh constructor.
22
     *
23
     * @param string $cnh Only accept numbers
24
     */
25 9
    public function __construct($cnh)
26
    {
27 9
        $cnh = preg_replace('/[\D]/', '', $cnh);
28 9
        $this->validate($cnh);
29 3
        $this->cnh = $cnh;
30 3
    }
31
32
    /**
33
     * Check if CNH is not empty and is a valid number.
34
     *
35
     * @param string $number
36
     *
37
     * @throws InvalidArgumentException when CNH is empty
38
     * @throws InvalidArgumentException when CNH is not valid number
39
     */
40 9
    private function validate($number)
41
    {
42 9
        if (empty($number)) {
43 3
            throw InvalidArgumentException::notEmpty(static::LABEL);
44
        }
45 6
        if (!$this->isValidCV($number)) {
46 3
            throw InvalidArgumentException::isNotValid(static::LABEL, $number);
47
        }
48 3
    }
49
50
    /**
51
     * Validates CNH is a valid number.
52
     *
53
     * @param string $number A number to be validate.
54
     *
55
     * @return bool Returns true if it is a valid number, otherwise false.
56
     */
57 6
    private function isValidCV($number)
58
    {
59 6
        $isRepeated = preg_match("/^{$number[0]}{" . static::LENGTH . '}$/', $number);
60
61 6
        if (strlen($number) != static::LENGTH || $isRepeated) {
62 2
            return false;
63
        }
64
65 4
        $baseNumber = substr($number, 0, -2);
66 4
        $firstDigit = $this->calculateFirstDigit($baseNumber);
67 4
        $secondDigit = $this->calculateSecondDigit("{$baseNumber}");
68
69 4
        return "{$firstDigit}{$secondDigit}" === substr($number, -2);
70
    }
71
72
    /**
73
     * Formats CNH number
74
     *
75
     * @return string Returns formatted number.
76
     */
77 1
    public function format()
78
    {
79 1
        return preg_replace('/[^\d]/', '', $this->cnh);
80
    }
81
82
    /**
83
     * Returns the CNH number
84
     *
85
     * @return string
86
     */
87 2
    public function __toString()
88
    {
89 2
        return $this->cnh;
90
    }
91
92 4
    private function calculateFirstDigit($number)
93
    {
94 4
        $calculator = new DigitCalculator($number);
95 4
        $calculator->withMultipliersInterval(1, 9);
96 4
        $calculator->replaceWhen('0', 10, 11);
97 4
        $calculator->withModule(DigitCalculator::MODULE_11);
98 4
        $firstDigit = $calculator->calculate();
99
100 4
        return "{$firstDigit}";
101
    }
102
103 4
    private function calculateSecondDigit($number)
104
    {
105 4
        $calculator = new DigitCalculator($number);
106 4
        $calculator->withMultipliers([9, 8, 7, 6, 5, 4, 3, 2, 1]);
107 4
        $calculator->replaceWhen('0', 10, 11);
108 4
        $calculator->withModule(DigitCalculator::MODULE_11);
109 4
        $secondDigit = $calculator->calculate();
110
111 4
        return "{$secondDigit}";
112
    }
113
}
114