Passed
Push — master ( 7a2bea...89672a )
by Antonio Oertel
35s
created

Cnpj::isValid()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

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