CpfCnpjValidator::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace WeDevBr\Bankly\Validators;
4
5
/**
6
 * ValidaCPFCNPJ valida e formata CPF e CNPJ
7
 *
8
 * Exemplo de uso:
9
 * $cpf_cnpj  = new ValidaCPFCNPJ('71569042000196');
10
 * $formatado = $cpf_cnpj->formata(); // 71.569.042/0001-96
11
 * $valida    = $cpf_cnpj->valida(); // True -> Válido
12
 *
13
 * @author Luiz Otávio Miranda <[email protected]>
14
 * @author Adeildo Amorim <[email protected]>
15
 * @version  v1.3
16
 * @access   public
17
 * @see      http://www.tutsup.com/
18
 */
19
20
class CpfCnpjValidator
21
{
22
    private $document;
23
    /**
24
     * Configura o valor (Construtor)
25
     *
26
     * Remove caracteres inválidos do CPF ou CNPJ
27
     *
28
     * @param string $document
29
     */
30
    public function __construct($document = null)
31
    {
32
        // Deixa apenas números no valor
33
        $this->document = preg_replace('/[^0-9]/', '', $document);
34
35
        // Garante que o valor é uma string
36
        $this->document = (string) $this->document;
37
    }
38
39
    /**
40
     * Verifica se é CPF ou CNPJ
41
     *
42
     * Se for CPF tem 11 caracteres, CNPJ tem 14
43
     *
44
     * @access protected
45
     * @return string
46
     * @throws \InvalidArgumentException;
47
     */
48
    protected function verifyCpfCnpj()
49
    {
50
        // Verifica CPF
51
        if (strlen($this->document) === 11) {
52
            return 'CPF';
53
        } elseif (strlen($this->document) === 14) { // Verifica CNPJ
54
            return 'CNPJ';
55
        }
56
        throw new \InvalidArgumentException('cpf_cnpj invalid');
57
    }
58
59
    /**
60
     * Multiplica dígitos vezes posições
61
     *
62
     * @access protected
63
     * @param  string    $digitos      Os digitos desejados
64
     * @param  int       $posicoes     A posição que vai iniciar a regressão
65
     * @param  int       $soma_digitos A soma das multiplicações entre posições e dígitos
66
     * @return int                     Os dígitos enviados concatenados com o último dígito
67
     */
68
    protected function calcPositionDigits($digitos, $posicoes = 10, $soma_digitos = 0)
69
    {
70
        // Faz a soma dos dígitos com a posição
71
        // Ex. para 10 posições:
72
        //   0    2    5    4    6    2    8    8   4
73
        // x10   x9   x8   x7   x6   x5   x4   x3  x2
74
        //   0 + 18 + 40 + 28 + 36 + 10 + 32 + 24 + 8 = 196
75
        for ($i = 0; $i < strlen($digitos); $i++) {
76
            // Preenche a soma com o dígito vezes a posição
77
            $soma_digitos = $soma_digitos + ($digitos[$i] * $posicoes);
78
79
            // Subtrai 1 da posição
80
            $posicoes--;
81
82
            // Parte específica para CNPJ
83
            // Ex.: 5-4-3-2-9-8-7-6-5-4-3-2
84
            if ($posicoes < 2) {
85
                // Retorno a posição para 9
86
                $posicoes = 9;
87
            }
88
        }
89
90
        // Captura o resto da divisão entre $soma_digitos dividido por 11
91
        // Ex.: 196 % 11 = 9
92
        $soma_digitos = $soma_digitos % 11;
93
94
        // Verifica se $soma_digitos é menor que 2
95
        if ($soma_digitos < 2) {
96
            // $soma_digitos agora será zero
97
            $soma_digitos = 0;
98
        } else {
99
            // Se for maior que 2, o resultado é 11 menos $soma_digitos
100
            // Ex.: 11 - 9 = 2
101
            // Nosso dígito procurado é 2
102
            $soma_digitos = 11 - $soma_digitos;
103
        }
104
105
        // Concatena mais um dígito aos primeiro nove dígitos
106
        // Ex.: 025462884 + 2 = 0254628842
107
        // Retorna
108
        return $digitos . $soma_digitos;
109
    }
110
111
    /**
112
     * Valida CPF
113
     *
114
     * @author                Luiz Otávio Miranda <[email protected]>
115
     * @access protected
116
     * @return bool           True para CPF correto - False para CPF incorreto
117
     */
118
    protected function validateCpf()
119
    {
120
        // Captura os 9 primeiros dígitos do CPF
121
        // Ex.: 02546288423 = 025462884
122
        $digitos = substr($this->document, 0, 9);
123
124
        // Faz o cálculo dos 9 primeiros dígitos do CPF para obter o primeiro dígito
125
        $new_cpf = $this->calcPositionDigits($digitos);
126
127
        // Faz o cálculo dos 10 dígitos do CPF para obter o último dígito
128
        $new_cpf = $this->calcPositionDigits($new_cpf, 11);
129
130
        // Verifica se o novo CPF gerado é idêntico ao CPF enviado
131
        return $new_cpf === $this->document;
132
    }
133
134
    /**
135
     * Valida CNPJ
136
     *
137
     * @author                  Luiz Otávio Miranda <[email protected]>
138
     * @access protected
139
     * @return bool             true para CNPJ correto
140
     */
141
    protected function validateCnpj()
142
    {
143
        // O valor original
144
        $original_cnpj = $this->document;
145
146
        // Captura os primeiros 12 números do CNPJ
147
        $primeiros_numeros_cnpj = substr($this->document, 0, 12);
148
149
        // Faz o primeiro cálculo
150
        $primeiro_calculo = $this->calcPositionDigits($primeiros_numeros_cnpj, 5);
151
152
        // O segundo cálculo é a mesma coisa do primeiro, porém, começa na posição 6
153
        $segundo_calculo = $this->calcPositionDigits($primeiro_calculo, 6);
154
155
        // Concatena o segundo dígito ao CNPJ
156
        $new_cnpj = $segundo_calculo;
157
158
        // Verifica se o CNPJ gerado é idêntico ao enviado
159
        return $new_cnpj === $original_cnpj;
160
    }
161
162
    /**
163
     * Valida
164
     *
165
     * Valida o CPF ou CNPJ
166
     *
167
     * @access public
168
     * @return bool      True para válido, false para inválido
169
     */
170
    public function validate()
171
    {
172
        // Valida CPF
173
        $validation = $this->verifyCpfCnpj();
174
        if ($validation === 'CPF') {
175
            // Retorna true para cpf válido
176
            return $this->validateCpf() && $this->verifySort(11);
177
        } elseif ($validation === 'CNPJ') { // Valida CNPJ
178
            // Retorna true para CNPJ válido
179
            return $this->validateCnpj() && $this->verifySort(14);
180
        } else {
181
            return false;
182
        }
183
    }
184
185
    /**
186
     * Formata CPF ou CNPJ
187
     *
188
     * @access public
189
     * @return string  CPF ou CNPJ formatado
190
     */
191
    public function format()
192
    {
193
        // O valor formatado
194
        $formatado = false;
195
        $validation = $this->verifyCpfCnpj();
196
197
        // Valida CPF
198
        if ($validation === 'CPF') {
199
            // Verifica se o CPF é válido
200
            if ($this->validateCpf()) {
201
                // Formata o CPF ###.###.###-##
202
                $formatado  = substr($this->document, 0, 3) . '.';
203
                $formatado .= substr($this->document, 3, 3) . '.';
204
                $formatado .= substr($this->document, 6, 3) . '-';
205
                $formatado .= substr($this->document, 9, 2) . '';
206
            }
207
        } elseif ($validation === 'CNPJ') { // Valida CNPJ
208
            // Verifica se o CPF é válido
209
            if ($this->validateCnpj()) {
210
                // Formata o CNPJ ##.###.###/####-##
211
                $formatado  = substr($this->document, 0, 2) . '.';
212
                $formatado .= substr($this->document, 2, 3) . '.';
213
                $formatado .= substr($this->document, 5, 3) . '/';
214
                $formatado .= substr($this->document, 8, 4) . '-';
215
                $formatado .= substr($this->document, 12, 14) . '';
216
            }
217
        }
218
219
        // Retorna o valor
220
        return $formatado;
221
    }
222
223
    /**
224
     * Método para verifica sequencia de números
225
     * @param  integer $multiplos Quantos números devem ser verificados
226
     * @return boolean
227
     */
228
    public function verifySort($multiplos)
229
    {
230
        // cpf
231
        for ($i = 0; $i < 10; $i++) {
232
            if (str_repeat($i, $multiplos) == $this->document) {
233
                return false;
234
            }
235
        }
236
237
        return true;
238
    }
239
}
240