Passed
Push — master ( 22a4bb...4eeb09 )
by Francimar
05:29
created

Inutilizacao   C

Complexity

Total Complexity 65

Size/Duplication

Total Lines 459
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 78.56%

Importance

Changes 0
Metric Value
wmc 65
lcom 1
cbo 6
dl 0
loc 459
ccs 55
cts 70
cp 0.7856
rs 5.7894
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 13 3
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 13 4
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
A loadNode() 0 58 3
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\Common\Util;
33
use NFe\Exception\ValidationException;
34
use FR3D\XmlDSig\Adapter\AdapterInterface;
35
use FR3D\XmlDSig\Adapter\XmlseclibsAdapter;
36
37
class Inutilizacao extends Retorno
0 ignored issues
show
Complexity introduced by
This class has a complexity of 65 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...
38
{
39
40
    private $id;
41
    private $ano;
42
    private $cnpj;
43
    private $modelo;
44
    private $serie;
45
    private $inicio;
46
    private $final;
47
    private $justificativa;
48
    private $numero;
49
50 1
    public function __construct($inutilizacao = array())
51
    {
52 1
        parent::__construct($inutilizacao);
53 1
    }
54
55
    /**
56
     * Formado por:
57
     * ID = Literal
58
     * 43 = Código Estado
59
     * 15 = Ano
60
     *
61
     * 00000000000000 = CNPJ
62
     * 55 = Modelo
63
     * 001 = Série
64
     * 000000411 =
65
     * Número Inicial
66
     * 000000411 = Número Final
67
     */
68
    public function getID($normalize = false)
69
    {
70
        if (!$normalize) {
71
            return $this->id;
72
        }
73
        return 'ID'.$this->id;
74
    }
75
76 1
    public function setID($id)
77
    {
78 1
        $this->id = $id;
79 1
        return $this;
80
    }
81
82
    public function getAno($normalize = false)
83
    {
84
        if (!$normalize) {
85
            return $this->ano;
86
        }
87
        return $this->ano % 100;
88
    }
89
90 1
    public function setAno($ano)
91
    {
92 1
        $this->ano = $ano;
93 1
        return $this;
94
    }
95
96
    public function getCNPJ($normalize = false)
97
    {
98
        if (!$normalize) {
99
            return $this->cnpj;
100
        }
101
        return $this->cnpj;
102
    }
103
104 1
    public function setCNPJ($cnpj)
105
    {
106 1
        $this->cnpj = $cnpj;
107 1
        return $this;
108
    }
109
110
    /**
111
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
112
     * @param boolean $normalize informa se o modelo deve estar no formato do XML
113
     * @return mixed modelo do Envio
114
     */
115
    public function getModelo($normalize = false)
116
    {
117
        if (!$normalize) {
118
            return $this->modelo;
119
        }
120
        switch ($this->modelo) {
121
            case Nota::MODELO_NFE:
122
                return '55';
123
            case Nota::MODELO_NFCE:
124
                return '65';
125
        }
126
        return $this->modelo;
127
    }
128
129
    /**
130
     * Altera o valor do Modelo para o informado no parâmetro
131
     * @param mixed $modelo novo valor para Modelo
132
     * @return Envio A própria instância da classe
133
     */
134 1
    public function setModelo($modelo)
135
    {
136
        switch ($modelo) {
137 1
            case '55':
138
                $modelo = Nota::MODELO_NFE;
139
                break;
140 1
            case '65':
141
                $modelo = Nota::MODELO_NFCE;
142
                break;
143
        }
144 1
        $this->modelo = $modelo;
145 1
        return $this;
146
    }
147
148
    public function getSerie($normalize = false)
149
    {
150
        if (!$normalize) {
151
            return $this->serie;
152
        }
153
        return $this->serie;
154
    }
155
156 1
    public function setSerie($serie)
157
    {
158 1
        $this->serie = $serie;
159 1
        return $this;
160
    }
161
162
    public function getInicio($normalize = false)
163
    {
164
        if (!$normalize) {
165
            return $this->inicio;
166
        }
167
        return $this->inicio;
168
    }
169
170 1
    public function setInicio($inicio)
171
    {
172 1
        $this->inicio = $inicio;
173 1
        return $this;
174
    }
175
176
    public function getFinal($normalize = false)
177
    {
178
        if (!$normalize) {
179
            return $this->final;
180
        }
181
        return $this->final;
182
    }
183
184 1
    public function setFinal($final)
185
    {
186 1
        $this->final = $final;
187 1
        return $this;
188
    }
189
190
    public function getJustificativa($normalize = false)
191
    {
192
        if (!$normalize) {
193
            return $this->justificativa;
194
        }
195
        return $this->justificativa;
196
    }
197
198 1
    public function setJustificativa($justificativa)
199
    {
200 1
        $this->justificativa = $justificativa;
201 1
        return $this;
202
    }
203
204
    public function getNumero($normalize = false)
205
    {
206
        if (!$normalize) {
207
            return $this->numero;
208
        }
209
        return $this->numero;
210
    }
211
212 1
    public function setNumero($numero)
213
    {
214 1
        $this->numero = $numero;
215 1
        return $this;
216
    }
217
218
    /**
219
     * Informa se os números foram inutilizados
220
     */
221
    public function isInutilizado()
222
    {
223
        return $this->getStatus() == '102';
224
    }
225
226
    public function toArray($recursive = false)
227
    {
228
        $inutilizacao = parent::toArray($recursive);
229
        $inutilizacao['id'] = $this->getID();
230
        $inutilizacao['ano'] = $this->getAno();
231
        $inutilizacao['cnpj'] = $this->getCNPJ();
232
        $inutilizacao['modelo'] = $this->getModelo();
233
        $inutilizacao['serie'] = $this->getSerie();
234
        $inutilizacao['inicio'] = $this->getInicio();
235
        $inutilizacao['final'] = $this->getFinal();
236
        $inutilizacao['justificativa'] = $this->getJustificativa();
237
        $inutilizacao['numero'] = $this->getNumero();
238
        return $inutilizacao;
239
    }
240
241 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...
242
    {
243 1
        if ($inutilizacao instanceof Inutilizacao) {
244
            $inutilizacao = $inutilizacao->toArray();
245 1
        } elseif (!is_array($inutilizacao)) {
246
            return $this;
247
        }
248 1
        parent::fromArray($inutilizacao);
249 1
        if (isset($inutilizacao['id'])) {
250
            $this->setID($inutilizacao['id']);
251
        } else {
252 1
            $this->setID(null);
253
        }
254 1
        if (isset($inutilizacao['ano'])) {
255
            $this->setAno($inutilizacao['ano']);
256
        } else {
257 1
            $this->setAno(null);
258
        }
259 1
        if (isset($inutilizacao['cnpj'])) {
260
            $this->setCNPJ($inutilizacao['cnpj']);
261
        } else {
262 1
            $this->setCNPJ(null);
263
        }
264 1
        if (isset($inutilizacao['modelo'])) {
265
            $this->setModelo($inutilizacao['modelo']);
266
        } else {
267 1
            $this->setModelo(null);
268
        }
269 1
        if (isset($inutilizacao['serie'])) {
270
            $this->setSerie($inutilizacao['serie']);
271
        } else {
272 1
            $this->setSerie(null);
273
        }
274 1
        if (isset($inutilizacao['inicio'])) {
275
            $this->setInicio($inutilizacao['inicio']);
276
        } else {
277 1
            $this->setInicio(null);
278
        }
279 1
        if (isset($inutilizacao['final'])) {
280
            $this->setFinal($inutilizacao['final']);
281
        } else {
282 1
            $this->setFinal(null);
283
        }
284 1
        if (isset($inutilizacao['justificativa'])) {
285
            $this->setJustificativa($inutilizacao['justificativa']);
286
        } else {
287 1
            $this->setJustificativa(null);
288
        }
289 1
        if (isset($inutilizacao['numero'])) {
290
            $this->setNumero($inutilizacao['numero']);
291
        } else {
292 1
            $this->setNumero(null);
293
        }
294 1
        return $this;
295
    }
296
297
    public function gerarID()
298
    {
299
        $id = sprintf(
300
            '%02d%02d%s%02d%03d%09d%09d',
301
            $this->getUF(true),
302
            $this->getAno(true), // 2 dígitos
303
            $this->getCNPJ(true),
304
            $this->getModelo(true),
305
            $this->getSerie(true),
306
            $this->getInicio(true),
307
            $this->getFinal(true)
308
        );
309
        return $id;
310
    }
311
312
    public function getNode($name = null)
313
    {
314
        $this->setID($this->gerarID());
315
316
        $dom = new \DOMDocument('1.0', 'UTF-8');
317
        $element = $dom->createElement(is_null($name)?'inutNFe':$name);
318
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', Nota::PORTAL);
319
        $versao = $dom->createAttribute('versao');
320
        $versao->value = Nota::VERSAO;
321
        $element->appendChild($versao);
322
323
        $info = $dom->createElement('infInut');
324
        $id = $dom->createAttribute('Id');
325
        $id->value = $this->getID(true);
326
        $info->appendChild($id);
327
328
        Util::appendNode($info, 'tpAmb', $this->getAmbiente(true));
329
        Util::appendNode($info, 'xServ', 'INUTILIZAR');
330
        Util::appendNode($info, 'cUF', $this->getUF(true));
331
        Util::appendNode($info, 'ano', $this->getAno(true));
332
        Util::appendNode($info, 'CNPJ', $this->getCNPJ(true));
333
        Util::appendNode($info, 'mod', $this->getModelo(true));
334
        Util::appendNode($info, 'serie', $this->getSerie(true));
335
        Util::appendNode($info, 'nNFIni', $this->getInicio(true));
336
        Util::appendNode($info, 'nNFFin', $this->getFinal(true));
337
        Util::appendNode($info, 'xJust', $this->getJustificativa(true));
338
        $element->appendChild($info);
339
        $dom->appendChild($element);
340
        return $element;
341
    }
342
343
    public function getReturnNode()
344
    {
345
        $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...
346
        $element = $this->getNode('retInutNFe');
347
        $dom = $element->ownerDocument;
348
        $info = $dom->getElementsByTagName('infInut')->item(0);
349
        $info->removeAttribute('Id');
350
        $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...
351
        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...
352
            $node = $info->getElementsByTagName($key)->item(0);
353
            $info->removeChild($node);
354
        }
355
        $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...
356
        foreach ($outros->childNodes as $node) {
357
            $node = $dom->importNode($node, true);
358
            $list = $info->getElementsByTagName($node->nodeName);
359
            if ($list->length == 1) {
360
                continue;
361
            }
362
            switch ($node->nodeName) {
363
                case 'dhRecbto':
364
                    $info->appendChild($node);
365
                    break;
366
                default:
367
                    $info->insertBefore($node, $uf);
368
            }
369
        }
370
        Util::appendNode($info, 'nProt', $this->getNumero(true));
371
        return $element;
372
    }
373
374
    public function loadNode($element, $name = null)
375
    {
376
        $name = is_null($name)?'infInut':$name;
377
        $element = parent::loadNode($element, $name);
378
        if (!$this->isInutilizado()) {
379
            return $element;
380
        }
381
        $this->setAno(
382
            Util::loadNode(
383
                $element,
384
                'ano',
385
                'Tag "ano" do campo "Ano" não encontrada'
386
            )
387
        );
388
        $this->setCNPJ(
389
            Util::loadNode(
390
                $element,
391
                'CNPJ',
392
                'Tag "CNPJ" do campo "CNPJ" não encontrada'
393
            )
394
        );
395
        $this->setModelo(
396
            Util::loadNode(
397
                $element,
398
                'mod',
399
                'Tag "mod" do campo "Modelo" não encontrada'
400
            )
401
        );
402
        $this->setSerie(
403
            Util::loadNode(
404
                $element,
405
                'serie',
406
                'Tag "serie" do campo "Serie" não encontrada'
407
            )
408
        );
409
        $this->setInicio(
410
            Util::loadNode(
411
                $element,
412
                'nNFIni',
413
                'Tag "nNFIni" do campo "Inicio" não encontrada'
414
            )
415
        );
416
        $this->setFinal(
417
            Util::loadNode(
418
                $element,
419
                'nNFFin',
420
                'Tag "nNFFin" do campo "Final" não encontrada'
421
            )
422
        );
423
        $this->setNumero(
424
            Util::loadNode(
425
                $element,
426
                'nProt',
427
                'Tag "nProt" do campo "Numero" não encontrada'
428
            )
429
        );
430
        return $element;
431
    }
432
433
    public function envia($dom)
434
    {
435
        $envio = new Envio();
436
        $envio->setServico(Envio::SERVICO_INUTILIZACAO);
437
        $envio->setAmbiente($this->getAmbiente());
438
        $envio->setModelo($this->getModelo());
439
        $envio->setEmissao(Nota::EMISSAO_NORMAL);
440
        $envio->setConteudo($dom);
441
        $resp = $envio->envia();
442
        $this->loadNode($resp);
443
        if (!$this->isInutilizado()) {
444
            throw new \Exception($this->getMotivo(), $this->getStatus());
445
        }
446
        return $this->getReturnNode()->ownerDocument;
447
    }
448
449
    /**
450
     * Assina o XML com a assinatura eletrônica do tipo A1
451
     */
452
    public function assinar($dom = null)
453
    {
454
        if (is_null($dom)) {
455
            $xml = $this->getNode();
456
            $dom = $xml->ownerDocument;
457
        }
458
        $config = SEFAZ::getInstance()->getConfiguracao();
459
460
        $adapter = new XmlseclibsAdapter();
461
        $adapter->setPrivateKey($config->getChavePrivada());
462
        $adapter->setPublicKey($config->getChavePublica());
463
        $adapter->addTransform(AdapterInterface::ENVELOPED);
464
        $adapter->addTransform(AdapterInterface::XML_C14N);
465
        $adapter->sign($dom, 'infInut');
466
        return $dom;
467
    }
468
469
    /**
470
     * Valida o documento após assinar
471
     */
472
    public function validar($dom)
473
    {
474
        $dom->loadXML($dom->saveXML());
475
        $xsd_path = dirname(__DIR__) . '/Core/schema';
476
        $xsd_file = $xsd_path . '/inutNFe_v3.10.xsd';
477
        if (!file_exists($xsd_file)) {
478
            throw new \Exception('O arquivo "'.$xsd_file.'" de esquema XSD não existe!', 404);
479
        }
480
        // Enable user error handling
481
        $save = libxml_use_internal_errors(true);
482
        if ($dom->schemaValidate($xsd_file)) {
483
            libxml_use_internal_errors($save);
484
            return $dom;
485
        }
486
        $msg = array();
487
        $errors = libxml_get_errors();
488
        foreach ($errors as $error) {
489
            $msg[] = 'Não foi possível validar o XML: '.$error->message;
490
        }
491
        libxml_clear_errors();
492
        libxml_use_internal_errors($save);
493
        throw new ValidationException($msg);
494
    }
495
}
496