Completed
Push — master ( c523cc...f6da78 )
by Francimar
05:08
created

Inutilizacao   C

Complexity

Total Complexity 68

Size/Duplication

Total Lines 435
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 19.06%

Importance

Changes 0
Metric Value
wmc 68
lcom 1
cbo 5
dl 0
loc 435
ccs 53
cts 278
cp 0.1906
rs 5.6756
c 0
b 0
f 0

29 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setID() 0 5 1
A setAno() 0 5 1
A setCNPJ() 0 5 1
A setModelo() 0 5 1
A setSerie() 0 5 1
A setInicio() 0 5 1
A setFinal() 0 5 1
A setJustificativa() 0 5 1
A setNumero() 0 5 1
A getID() 0 7 2
A getAno() 0 7 2
A getCNPJ() 0 7 2
A getModelo() 0 7 2
A getSerie() 0 7 2
A getInicio() 0 7 2
A getFinal() 0 7 2
A getJustificativa() 0 7 2
A getNumero() 0 7 2
A isInutilizado() 0 4 1
A toArray() 0 14 1
F fromArray() 0 55 12
A gerarID() 0 14 1
B getNode() 0 30 2
B getReturnNode() 0 30 5
C loadNode() 0 58 10
A envia() 0 15 2
A assinar() 0 16 2
B validar() 0 23 4

How to fix   Complexity   

Complex Class

Complex classes like Inutilizacao often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Inutilizacao, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * MIT License
4
 *
5
 * Copyright (c) 2016 MZ Desenvolvimento de Sistemas LTDA
6
 *
7
 * @author Francimar Alves <[email protected]>
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to deal
11
 * in the Software without restriction, including without limitation the rights
12
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 * copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
 * SOFTWARE.
26
 *
27
 */
28
namespace NFe\Task;
29
30
use NFe\Core\Nota;
31
use NFe\Core\SEFAZ;
32
use NFe\Exception\ValidationException;
33
use FR3D\XmlDSig\Adapter\AdapterInterface;
34
use FR3D\XmlDSig\Adapter\XmlseclibsAdapter;
35
36
class Inutilizacao extends Retorno
0 ignored issues
show
Complexity introduced by
This class has a complexity of 68 which exceeds the configured maximum of 50.

The class complexity is the sum of the complexity of all methods. A very high value is usually an indication that your class does not follow the single reponsibility principle and does more than one job.

Some resources for further reading:

You can also find more detailed suggestions for refactoring in the “Code” section of your repository.

Loading history...
37
{
38
39
    private $id;
40
    private $ano;
41
    private $cnpj;
42
    private $modelo;
43
    private $serie;
44
    private $inicio;
45
    private $final;
46
    private $justificativa;
47
    private $numero;
48
49 1
    public function __construct($inutilizacao = array())
50
    {
51 1
        parent::__construct($inutilizacao);
52 1
    }
53
54
    /**
55
     * Formado por:
56
     * ID = Literal
57
     * 43 = Código Estado
58
     * 15 = Ano
59
     *
60
     * 00000000000000 = CNPJ
61
     * 55 = Modelo
62
     * 001 = Série
63
     * 000000411 =
64
     * Número Inicial
65
     * 000000411 = Número Final
66
     */
67
    public function getID($normalize = false)
68
    {
69
        if (!$normalize) {
70
            return $this->id;
71
        }
72
        return 'ID'.$this->id;
73
    }
74
75 1
    public function setID($id)
76
    {
77 1
        $this->id = $id;
78 1
        return $this;
79
    }
80
81
    public function getAno($normalize = false)
82
    {
83
        if (!$normalize) {
84
            return $this->ano;
85
        }
86
        return $this->ano % 100;
87
    }
88
89 1
    public function setAno($ano)
90
    {
91 1
        $this->ano = $ano;
92 1
        return $this;
93
    }
94
95
    public function getCNPJ($normalize = false)
96
    {
97
        if (!$normalize) {
98
            return $this->cnpj;
99
        }
100
        return $this->cnpj;
101
    }
102
103 1
    public function setCNPJ($cnpj)
104
    {
105 1
        $this->cnpj = $cnpj;
106 1
        return $this;
107
    }
108
109
    public function getModelo($normalize = false)
110
    {
111
        if (!$normalize) {
112
            return $this->modelo;
113
        }
114
        return $this->modelo;
115
    }
116
117 1
    public function setModelo($modelo)
118
    {
119 1
        $this->modelo = $modelo;
120 1
        return $this;
121
    }
122
123
    public function getSerie($normalize = false)
124
    {
125
        if (!$normalize) {
126
            return $this->serie;
127
        }
128
        return $this->serie;
129
    }
130
131 1
    public function setSerie($serie)
132
    {
133 1
        $this->serie = $serie;
134 1
        return $this;
135
    }
136
137
    public function getInicio($normalize = false)
138
    {
139
        if (!$normalize) {
140
            return $this->inicio;
141
        }
142
        return $this->inicio;
143
    }
144
145 1
    public function setInicio($inicio)
146
    {
147 1
        $this->inicio = $inicio;
148 1
        return $this;
149
    }
150
151
    public function getFinal($normalize = false)
152
    {
153
        if (!$normalize) {
154
            return $this->final;
155
        }
156
        return $this->final;
157
    }
158
159 1
    public function setFinal($final)
160
    {
161 1
        $this->final = $final;
162 1
        return $this;
163
    }
164
165
    public function getJustificativa($normalize = false)
166
    {
167
        if (!$normalize) {
168
            return $this->justificativa;
169
        }
170
        return $this->justificativa;
171
    }
172
173 1
    public function setJustificativa($justificativa)
174
    {
175 1
        $this->justificativa = $justificativa;
176 1
        return $this;
177
    }
178
179
    public function getNumero($normalize = false)
180
    {
181
        if (!$normalize) {
182
            return $this->numero;
183
        }
184
        return $this->numero;
185
    }
186
187 1
    public function setNumero($numero)
188
    {
189 1
        $this->numero = $numero;
190 1
        return $this;
191
    }
192
193
    /**
194
     * Informa se os números foram inutilizados
195
     */
196
    public function isInutilizado()
197
    {
198
        return $this->getStatus() == '102';
199
    }
200
201
    public function toArray()
202
    {
203
        $inutilizacao = parent::toArray();
204
        $inutilizacao['id'] = $this->getID();
205
        $inutilizacao['ano'] = $this->getAno();
206
        $inutilizacao['cnpj'] = $this->getCNPJ();
207
        $inutilizacao['modelo'] = $this->getModelo();
208
        $inutilizacao['serie'] = $this->getSerie();
209
        $inutilizacao['inicio'] = $this->getInicio();
210
        $inutilizacao['final'] = $this->getFinal();
211
        $inutilizacao['justificativa'] = $this->getJustificativa();
212
        $inutilizacao['numero'] = $this->getNumero();
213
        return $inutilizacao;
214
    }
215
216 1
    public function fromArray($inutilizacao = array())
0 ignored issues
show
Complexity introduced by
This operation has 1536 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

You can also find more information in the “Code” section of your repository.

Loading history...
217
    {
218 1
        if ($inutilizacao instanceof Inutilizacao) {
219
            $inutilizacao = $inutilizacao->toArray();
220 1
        } elseif (!is_array($inutilizacao)) {
221
            return $this;
222
        }
223 1
        parent::fromArray($inutilizacao);
224 1
        if (isset($inutilizacao['id'])) {
225
            $this->setID($inutilizacao['id']);
226
        } else {
227 1
            $this->setID(null);
228
        }
229 1
        if (isset($inutilizacao['ano'])) {
230
            $this->setAno($inutilizacao['ano']);
231
        } else {
232 1
            $this->setAno(null);
233
        }
234 1
        if (isset($inutilizacao['cnpj'])) {
235
            $this->setCNPJ($inutilizacao['cnpj']);
236
        } else {
237 1
            $this->setCNPJ(null);
238
        }
239 1
        if (isset($inutilizacao['modelo'])) {
240
            $this->setModelo($inutilizacao['modelo']);
241
        } else {
242 1
            $this->setModelo(null);
243
        }
244 1
        if (isset($inutilizacao['serie'])) {
245
            $this->setSerie($inutilizacao['serie']);
246
        } else {
247 1
            $this->setSerie(null);
248
        }
249 1
        if (isset($inutilizacao['inicio'])) {
250
            $this->setInicio($inutilizacao['inicio']);
251
        } else {
252 1
            $this->setInicio(null);
253
        }
254 1
        if (isset($inutilizacao['final'])) {
255
            $this->setFinal($inutilizacao['final']);
256
        } else {
257 1
            $this->setFinal(null);
258
        }
259 1
        if (isset($inutilizacao['justificativa'])) {
260
            $this->setJustificativa($inutilizacao['justificativa']);
261
        } else {
262 1
            $this->setJustificativa(null);
263
        }
264 1
        if (isset($inutilizacao['numero'])) {
265
            $this->setNumero($inutilizacao['numero']);
266
        } else {
267 1
            $this->setNumero(null);
268
        }
269 1
        return $this;
270
    }
271
272
    public function gerarID()
273
    {
274
        $id = sprintf(
275
            '%02d%02d%s%02d%03d%09d%09d',
276
            $this->getUF(true),
277
            $this->getAno(true), // 2 dígitos
278
            $this->getCNPJ(true),
279
            $this->getModelo(true),
280
            $this->getSerie(true),
281
            $this->getInicio(true),
282
            $this->getFinal(true)
283
        );
284
        return $id;
285
    }
286
287
    public function getNode($name = null)
288
    {
289
        $this->setID($this->gerarID());
290
291
        $dom = new \DOMDocument('1.0', 'UTF-8');
292
        $element = $dom->createElement(is_null($name)?'inutNFe':$name);
293
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', Nota::PORTAL);
294
        $versao = $dom->createAttribute('versao');
295
        $versao->value = Nota::VERSAO;
296
        $element->appendChild($versao);
297
298
        $info = $dom->createElement('infInut');
299
        $id = $dom->createAttribute('Id');
300
        $id->value = $this->getID(true);
301
        $info->appendChild($id);
302
303
        $info->appendChild($dom->createElement('tpAmb', $this->getAmbiente(true)));
304
        $info->appendChild($dom->createElement('xServ', 'INUTILIZAR'));
305
        $info->appendChild($dom->createElement('cUF', $this->getUF(true)));
306
        $info->appendChild($dom->createElement('ano', $this->getAno(true)));
307
        $info->appendChild($dom->createElement('CNPJ', $this->getCNPJ(true)));
308
        $info->appendChild($dom->createElement('mod', $this->getModelo(true)));
309
        $info->appendChild($dom->createElement('serie', $this->getSerie(true)));
310
        $info->appendChild($dom->createElement('nNFIni', $this->getInicio(true)));
311
        $info->appendChild($dom->createElement('nNFFin', $this->getFinal(true)));
312
        $info->appendChild($dom->createElement('xJust', $this->getJustificativa(true)));
313
        $element->appendChild($info);
314
        $dom->appendChild($element);
315
        return $element;
316
    }
317
318
    public function getReturnNode()
319
    {
320
        $outros = parent::getNode('infInut');
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getNode() instead of getReturnNode()). Are you sure this is correct? If so, you might want to change this to $this->getNode().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
321
        $element = $this->getNode('retInutNFe');
322
        $dom = $element->ownerDocument;
323
        $info = $dom->getElementsByTagName('infInut')->item(0);
324
        $info->removeAttribute('Id');
325
        $removeTags = array('tpAmb', 'xServ', 'xJust');
0 ignored issues
show
Coding Style introduced by
$removeTags does not seem to conform to the naming convention (^[a-z_][a-z0-9_]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
326
        foreach ($removeTags as $key) {
0 ignored issues
show
Coding Style introduced by
$removeTags does not seem to conform to the naming convention (^[a-z_][a-z0-9_]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
327
            $node = $info->getElementsByTagName($key)->item(0);
328
            $info->removeChild($node);
329
        }
330
        $uf = $info->getElementsByTagName('cUF')->item(0);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $uf. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
331
        foreach ($outros->childNodes as $node) {
332
            $node = $dom->importNode($node, true);
333
            $list = $info->getElementsByTagName($node->nodeName);
334
            if ($list->length == 1) {
335
                continue;
336
            }
337
            switch ($node->nodeName) {
338
                case 'dhRecbto':
339
                    $info->appendChild($node);
340
                    break;
341
                default:
342
                    $info->insertBefore($node, $uf);
343
            }
344
        }
345
        $info->appendChild($dom->createElement('nProt', $this->getNumero(true)));
346
        return $element;
347
    }
348
349
    public function loadNode($element, $name = null)
0 ignored issues
show
Complexity introduced by
This operation has 1280 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

You can also find more information in the “Code” section of your repository.

Loading history...
350
    {
351
        $name = is_null($name)?'infInut':$name;
352
        $element = parent::loadNode($element, $name);
353
        if (!$this->isInutilizado()) {
354
            return $element;
355
        }
356
        $_fields = $element->getElementsByTagName('ano');
357
        if ($_fields->length > 0) {
358
            $ano = $_fields->item(0)->nodeValue;
359
        } else {
360
            throw new \Exception('Tag "ano" do campo "Ano" não encontrada', 404);
361
        }
362
        $this->setAno($ano);
363
        $_fields = $element->getElementsByTagName('CNPJ');
364
        if ($_fields->length > 0) {
365
            $cnpj = $_fields->item(0)->nodeValue;
366
        } else {
367
            throw new \Exception('Tag "CNPJ" do campo "CNPJ" não encontrada', 404);
368
        }
369
        $this->setCNPJ($cnpj);
370
        $_fields = $element->getElementsByTagName('mod');
371
        if ($_fields->length > 0) {
372
            $modelo = $_fields->item(0)->nodeValue;
373
        } else {
374
            throw new \Exception('Tag "mod" do campo "Modelo" não encontrada', 404);
375
        }
376
        $this->setModelo($modelo);
377
        $_fields = $element->getElementsByTagName('serie');
378
        if ($_fields->length > 0) {
379
            $serie = $_fields->item(0)->nodeValue;
380
        } else {
381
            throw new \Exception('Tag "serie" do campo "Serie" não encontrada', 404);
382
        }
383
        $this->setSerie($serie);
384
        $_fields = $element->getElementsByTagName('nNFIni');
385
        if ($_fields->length > 0) {
386
            $inicio = $_fields->item(0)->nodeValue;
387
        } else {
388
            throw new \Exception('Tag "nNFIni" do campo "Inicio" não encontrada', 404);
389
        }
390
        $this->setInicio($inicio);
391
        $_fields = $element->getElementsByTagName('nNFFin');
392
        if ($_fields->length > 0) {
393
            $final = $_fields->item(0)->nodeValue;
394
        } else {
395
            throw new \Exception('Tag "nNFFin" do campo "Final" não encontrada', 404);
396
        }
397
        $this->setFinal($final);
398
        $_fields = $element->getElementsByTagName('nProt');
399
        if ($_fields->length > 0) {
400
            $numero = $_fields->item(0)->nodeValue;
401
        } else {
402
            throw new \Exception('Tag "nProt" do campo "Numero" não encontrada', 404);
403
        }
404
        $this->setNumero($numero);
405
        return $element;
406
    }
407
408
    public function envia($dom)
409
    {
410
        $envio = new Envio();
411
        $envio->setServico(Envio::SERVICO_INUTILIZACAO);
412
        $envio->setAmbiente($this->getAmbiente());
413
        $envio->setModelo($this->getModelo());
414
        $envio->setEmissao(Nota::EMISSAO_NORMAL);
415
        $envio->setConteudo($dom);
416
        $resp = $envio->envia();
417
        $this->loadNode($resp);
418
        if (!$this->isInutilizado()) {
419
            throw new \Exception($this->getMotivo(), $this->getStatus());
420
        }
421
        return $this->getReturnNode()->ownerDocument;
422
    }
423
424
    /**
425
     * Assina o XML com a assinatura eletrônica do tipo A1
426
     */
427
    public function assinar($dom = null)
428
    {
429
        if (is_null($dom)) {
430
            $xml = $this->getNode();
431
            $dom = $xml->ownerDocument;
432
        }
433
        $config = SEFAZ::getInstance()->getConfiguracao();
434
435
        $adapter = new XmlseclibsAdapter();
436
        $adapter->setPrivateKey($config->getChavePrivada());
437
        $adapter->setPublicKey($config->getChavePublica());
438
        $adapter->addTransform(AdapterInterface::ENVELOPED);
439
        $adapter->addTransform(AdapterInterface::XML_C14N);
440
        $adapter->sign($dom, 'infInut');
441
        return $dom;
442
    }
443
444
    /**
445
     * Valida o documento após assinar
446
     */
447
    public function validar($dom)
448
    {
449
        $dom->loadXML($dom->saveXML());
450
        $xsd_path = dirname(__DIR__) . '/Core/schema';
451
        $xsd_file = $xsd_path . '/inutNFe_v3.10.xsd';
452
        if (!file_exists($xsd_file)) {
453
            throw new \Exception('O arquivo "'.$xsd_file.'" de esquema XSD não existe!', 404);
454
        }
455
        // Enable user error handling
456
        $save = libxml_use_internal_errors(true);
457
        if ($dom->schemaValidate($xsd_file)) {
458
            libxml_use_internal_errors($save);
459
            return $dom;
460
        }
461
        $msg = array();
462
        $errors = libxml_get_errors();
463
        foreach ($errors as $error) {
464
            $msg[] = 'Não foi possível validar o XML: '.$error->message;
465
        }
466
        libxml_clear_errors();
467
        libxml_use_internal_errors($save);
468
        throw new ValidationException($msg);
469
    }
470
}
471