Passed
Push — master ( a89aec...47ded6 )
by Roberto
04:31 queued 02:15
created

Complements   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 348
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 43
lcom 1
cbo 2
dl 0
loc 348
ccs 0
cts 257
cp 0
rs 8.96
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A toAuthorize() 0 11 4
A b2bTag() 0 38 3
B cancelRegister() 0 54 7
C addInutNFeProtocol() 0 62 14
C addNFeProtocol() 0 64 10
A addEnvEventoProtocol() 0 43 4
A join() 0 10 1

How to fix   Complexity   

Complex Class

Complex classes like Complements 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 Complements, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace NFePHP\NFe;
4
5
use NFePHP\Common\Strings;
6
use NFePHP\NFe\Common\Standardize;
7
use NFePHP\NFe\Exception\DocumentsException;
8
use DOMDocument;
9
10
class Complements
11
{
12
    protected static $urlPortal = 'http://www.portalfiscal.inf.br/nfe';
13
14
    /**
15
     * Authorize document adding his protocol
16
     * @param string $request
17
     * @param string $response
18
     * @return string
19
     */
20
    public static function toAuthorize($request, $response)
21
    {
22
        $st = new Standardize();
23
        $key = ucfirst($st->whichIs($request));
24
        if ($key != 'NFe' && $key != 'EnvEvento' && $key != 'InutNFe') {
25
            //wrong document, this document is not able to recieve a protocol
26
            throw DocumentsException::wrongDocument(0, $key);
27
        }
28
        $func = "add".$key."Protocol";
29
        return self::$func($request, $response);
30
    }
31
32
    /**
33
     * Add tags B2B, as example ANFAVEA
34
     * @param  string $nfe xml nfe string content
35
     * @param  string $b2b xml b2b string content
36
     * @param  string $tagB2B name B2B tag default 'NFeB2BFin' from ANFAVEA
37
     * @return string
38
     * @throws \InvalidArgumentException
39
     */
40
    public static function b2bTag($nfe, $b2b, $tagB2B = 'NFeB2BFin')
41
    {
42
        $domnfe = new DOMDocument('1.0', 'UTF-8');
43
        $domnfe->preserveWhiteSpace = false;
44
        $domnfe->formatOutput = false;
45
        $domnfe->loadXML($nfe);
46
        $nodenfe = $domnfe->getElementsByTagName('nfeProc')->item(0);
47
        if (empty($nodenfe)) {
48
            //not is NFe or dont protocoladed doc
49
            throw DocumentsException::wrongDocument(1);
50
        }
51
        //carrega o arquivo B2B
52
        $domb2b = new DOMDocument('1.0', 'UTF-8');
53
        $domb2b->preserveWhiteSpace = false;
54
        $domb2b->formatOutput = false;
55
        $domb2b->loadXML($b2b);
56
        $nodeb2b = $domnfe->getElementsByTagName($tagB2B)->item(0);
57
        if (empty($nodeb2b)) {
58
            //xml is not protocoladed or dont is a NFe
59
            throw DocumentsException::wrongDocument(2);
60
        }
61
        //cria a NFe processada com a tag do protocolo
62
        $procb2b = new DOMDocument('1.0', 'UTF-8');
63
        $procb2b->preserveWhiteSpace = false;
64
        $procb2b->formatOutput = false;
65
        //cria a tag nfeProc
66
        $nfeProcB2B = $procb2b->createElement('nfeProcB2B');
67
        $procb2b->appendChild($nfeProcB2B);
68
        //inclui a tag NFe
69
        $node1 = $procb2b->importNode($nodenfe, true);
70
        $nfeProcB2B->appendChild($node1);
71
        //inclui a tag NFeB2BFin
72
        $node2 = $procb2b->importNode($nodeb2b, true);
73
        $nfeProcB2B->appendChild($node2);
74
        $nfeb2bXML = $procb2b->saveXML();
75
        $nfeb2bXMLString = str_replace(array("\n","\r","\s"), '', $nfeb2bXML);
76
        return (string) $nfeb2bXMLString;
77
    }
78
79
    /**
80
     * Add cancel protocol to a autorized NFe
81
     * if event is not a cancellation will return
82
     * the same autorized NFe passing
83
     * NOTE: This action is not necessary, I use only for my needs to
84
     *       leave the NFe marked as Canceled in order to avoid mistakes
85
     *       after its cancellation.
86
     * @param  string $nfe content of autorized NFe XML
87
     * @param  string $cancelamento content of SEFAZ response
88
     * @return string
89
     * @throws \InvalidArgumentException
90
     */
91
    public static function cancelRegister($nfe, $cancelamento)
92
    {
93
        $procXML = $nfe;
94
        $domnfe = new DOMDocument('1.0', 'utf-8');
95
        $domnfe->formatOutput = false;
96
        $domnfe->preserveWhiteSpace = false;
97
        $domnfe->loadXML($nfe);
98
        $proNFe = $domnfe->getElementsByTagName('protNFe')->item(0);
99
        if (empty($proNFe)) {
100
            //not protocoladed NFe
101
            throw DocumentsException::wrongDocument(1);
102
        }
103
        $chaveNFe = $proNFe->getElementsByTagName('chNFe')->item(0)->nodeValue;
104
105
        $domcanc = new DOMDocument('1.0', 'utf-8');
106
        $domcanc->formatOutput = false;
107
        $domcanc->preserveWhiteSpace = false;
108
        $domcanc->loadXML($cancelamento);
109
        $eventos = $domcanc->getElementsByTagName('retEvento');
110
        foreach ($eventos as $evento) {
111
            $infEvento = $evento->getElementsByTagName('infEvento')->item(0);
112
            $cStat = $infEvento->getElementsByTagName('cStat')
113
                ->item(0)
114
                ->nodeValue;
115
            $nProt = $infEvento->getElementsByTagName('nProt')
116
                ->item(0)
117
                ->nodeValue;
118
            $chaveEvento = $infEvento->getElementsByTagName('chNFe')
119
                ->item(0)
120
                ->nodeValue;
121
            $tpEvento = $infEvento->getElementsByTagName('tpEvento')
122
                ->item(0)
123
                ->nodeValue;
124
            if (in_array($cStat, ['135', '136', '155'])
125
                && ($tpEvento == Tools::EVT_CANCELA
126
                    || $tpEvento == Tools::EVT_CANCELASUBSTITUICAO
127
                )
128
                && $chaveEvento == $chaveNFe
129
            ) {
130
                $proNFe->getElementsByTagName('cStat')
131
                    ->item(0)
132
                    ->nodeValue = '101';
133
                $proNFe->getElementsByTagName('nProt')
134
                    ->item(0)
135
                    ->nodeValue = $nProt;
136
                $proNFe->getElementsByTagName('xMotivo')
137
                    ->item(0)
138
                    ->nodeValue = 'Cancelamento de NF-e homologado';
139
                $procXML = Strings::clearProtocoledXML($domnfe->saveXML());
140
                break;
141
            }
142
        }
143
        return $procXML;
144
    }
145
146
    /**
147
     * Authorize Inutilization of numbers
148
     * @param string $request
149
     * @param string $response
150
     * @return string
151
     * @throws \InvalidArgumentException
152
     */
153
    protected static function addInutNFeProtocol($request, $response)
154
    {
155
        $req = new DOMDocument('1.0', 'UTF-8');
156
        $req->preserveWhiteSpace = false;
157
        $req->formatOutput = false;
158
        $req->loadXML($request);
159
        $inutNFe = $req->getElementsByTagName('inutNFe')->item(0);
160
        $versao = $inutNFe->getAttribute("versao");
161
        $infInut = $req->getElementsByTagName('infInut')->item(0);
162
        $tpAmb = $infInut->getElementsByTagName('tpAmb')->item(0)->nodeValue;
163
        $cUF = !empty($infInut->getElementsByTagName('cUF')->item(0)->nodeValue)
164
            ? $infInut->getElementsByTagName('cUF')->item(0)->nodeValue : '';
165
        $ano = $infInut->getElementsByTagName('ano')->item(0)->nodeValue;
166
        $cnpj = $infInut->getElementsByTagName('CNPJ')->item(0)->nodeValue;
167
        $mod = $infInut->getElementsByTagName('mod')->item(0)->nodeValue;
168
        $serie = $infInut->getElementsByTagName('serie')->item(0)->nodeValue;
169
        $nNFIni = $infInut->getElementsByTagName('nNFIni')->item(0)->nodeValue;
170
        $nNFFin = $infInut->getElementsByTagName('nNFFin')->item(0)->nodeValue;
171
172
        $ret = new DOMDocument('1.0', 'UTF-8');
173
        $ret->preserveWhiteSpace = false;
174
        $ret->formatOutput = false;
175
        $ret->loadXML($response);
176
        $retInutNFe = $ret->getElementsByTagName('retInutNFe')->item(0);
177
        if (!isset($retInutNFe)) {
178
            throw DocumentsException::wrongDocument(3, "&lt;retInutNFe;");
179
        }
180
        $retversao = $retInutNFe->getAttribute("versao");
181
        $retInfInut = $ret->getElementsByTagName('infInut')->item(0);
182
        $cStat = $retInfInut->getElementsByTagName('cStat')->item(0)->nodeValue;
183
        $xMotivo = $retInfInut->getElementsByTagName('xMotivo')->item(0)->nodeValue;
184
        if ($cStat != 102) {
185
            throw DocumentsException::wrongDocument(4, "[$cStat] $xMotivo.");
186
        }
187
        $rettpAmb = $retInfInut->getElementsByTagName('tpAmb')->item(0)->nodeValue;
188
        $retcUF = !empty($retInfInut->getElementsByTagName('cUF')->item(0)->nodeValue)
189
            ? $retInfInut->getElementsByTagName('cUF')->item(0)->nodeValue : $cUF;
190
        $retano = $retInfInut->getElementsByTagName('ano')->item(0)->nodeValue;
191
        $retcnpj = $retInfInut->getElementsByTagName('CNPJ')->item(0)->nodeValue;
192
        $retmod = $retInfInut->getElementsByTagName('mod')->item(0)->nodeValue;
193
        $retserie = $retInfInut->getElementsByTagName('serie')->item(0)->nodeValue;
194
        $retnNFIni = $retInfInut->getElementsByTagName('nNFIni')->item(0)->nodeValue;
195
        $retnNFFin = $retInfInut->getElementsByTagName('nNFFin')->item(0)->nodeValue;
196
        if ($versao != $retversao ||
197
            $tpAmb != $rettpAmb ||
198
            $cUF != $retcUF ||
199
            $ano != $retano ||
200
            $cnpj != $retcnpj ||
201
            $mod != $retmod ||
202
            $serie != $retserie ||
203
            $nNFIni != $retnNFIni ||
204
            $nNFFin != $retnNFFin
205
        ) {
206
            throw DocumentsException::wrongDocument(5);
207
        }
208
        return self::join(
209
            $req->saveXML($inutNFe),
210
            $ret->saveXML($retInutNFe),
211
            'procInutNFe',
212
            $versao
213
        );
214
    }
215
216
    /**
217
     * Authorize NFe
218
     * @param string $request
219
     * @param string $response
220
     * @return string
221
     * @throws \InvalidArgumentException
222
     */
223
    protected static function addNFeProtocol($request, $response)
224
    {
225
        $req = new DOMDocument('1.0', 'UTF-8');
226
        $req->preserveWhiteSpace = false;
227
        $req->formatOutput = false;
228
        $req->loadXML($request);
229
230
        $nfe = $req->getElementsByTagName('NFe')->item(0);
231
        $infNFe = $req->getElementsByTagName('infNFe')->item(0);
232
        $versao = $infNFe->getAttribute("versao");
233
        $chave = preg_replace('/[^0-9]/', '', $infNFe->getAttribute("Id"));
234
        $digNFe = $req->getElementsByTagName('DigestValue')
235
            ->item(0)
236
            ->nodeValue;
237
238
        $ret = new DOMDocument('1.0', 'UTF-8');
239
        $ret->preserveWhiteSpace = false;
240
        $ret->formatOutput = false;
241
        $ret->loadXML($response);
242
        $retProt = !empty($ret->getElementsByTagName('protNFe')) ? $ret->getElementsByTagName('protNFe') : null;
243
        if ($retProt === null) {
244
            throw DocumentsException::wrongDocument(3, "&lt;protNFe&gt;");
245
        }
246
        $digProt = null;
247
        foreach ($retProt as $rp) {
248
            $infProt = $rp->getElementsByTagName('infProt')->item(0);
249
            $cStat = $infProt->getElementsByTagName('cStat')->item(0)->nodeValue;
250
            $xMotivo = $infProt->getElementsByTagName('xMotivo')->item(0)->nodeValue;
251
            $dig = $infProt->getElementsByTagName("digVal")->item(0);
252
            $key = $infProt->getElementsByTagName("chNFe")->item(0)->nodeValue;
253
            if (isset($dig)) {
254
                $digProt = $dig->nodeValue;
255
                if ($digProt == $digNFe && $chave == $key) {
256
                    //100 Autorizado
257
                    //150 Autorizado fora do prazo
258
                    //110 Uso Denegado
259
                    //205 NFe Denegada
260
                    //301 Uso denegado por irregularidade fiscal do emitente
261
                    //302 Uso denegado por irregularidade fiscal do destinatário
262
                    //303 Uso Denegado Destinatario nao habilitado a operar na UF
263
                    $cstatpermit = ['100', '150', '110', '205', '301', '302', '303'];
264
                    if (!in_array($cStat, $cstatpermit)) {
265
                        throw DocumentsException::wrongDocument(4, "[$cStat] $xMotivo");
266
                    }
267
                    return self::join(
268
                        $req->saveXML($nfe),
269
                        $ret->saveXML($rp),
270
                        'nfeProc',
271
                        $versao
272
                    );
273
                }
274
            }
275
        }
276
        if (empty($digProt)) {
277
            $prot = $ret->getElementsByTagName('protNFe')->item(0);
278
            $cStat = $prot->getElementsByTagName('cStat')->item(0)->nodeValue;
279
            $xMotivo= $prot->getElementsByTagName('xMotivo')->item(0)->nodeValue;
280
            throw DocumentsException::wrongDocument(18, "[{$cStat}] {$xMotivo}");
281
        }
282
        if ($digNFe !== $digProt) {
283
            throw DocumentsException::wrongDocument(5, "Os digest são diferentes");
284
        }
285
        return $req->saveXML();
286
    }
287
288
    /**
289
     * Authorize Event
290
     * @param string $request
291
     * @param string $response
292
     * @return string
293
     * @throws \InvalidArgumentException
294
     */
295
    protected static function addEnvEventoProtocol($request, $response)
296
    {
297
        $ev = new \DOMDocument('1.0', 'UTF-8');
298
        $ev->preserveWhiteSpace = false;
299
        $ev->formatOutput = false;
300
        $ev->loadXML($request);
301
        //extrai numero do lote do envio
302
        $envLote = $ev->getElementsByTagName('idLote')->item(0)->nodeValue;
303
        //extrai tag evento do xml origem (solicitação)
304
        $event = $ev->getElementsByTagName('evento')->item(0);
305
        $versao = $event->getAttribute('versao');
306
307
        $ret = new \DOMDocument('1.0', 'UTF-8');
308
        $ret->preserveWhiteSpace = false;
309
        $ret->formatOutput = false;
310
        $ret->loadXML($response);
311
        //extrai numero do lote da resposta
312
        $resLote = $ret->getElementsByTagName('idLote')->item(0)->nodeValue;
313
        //extrai a rag retEvento da resposta (retorno da SEFAZ)
314
        $retEv = $ret->getElementsByTagName('retEvento')->item(0);
315
        $cStat  = $retEv->getElementsByTagName('cStat')->item(0)->nodeValue;
316
        $xMotivo = $retEv->getElementsByTagName('xMotivo')->item(0)->nodeValue;
317
        $tpEvento = $retEv->getElementsByTagName('tpEvento')->item(0)->nodeValue;
318
        $cStatValids = ['135', '136'];
319
        if ($tpEvento == Tools::EVT_CANCELA) {
320
            $cStatValids[] = '155';
321
        }
322
        if (!in_array($cStat, $cStatValids)) {
323
            throw DocumentsException::wrongDocument(4, "[$cStat] $xMotivo");
324
        }
325
        if ($resLote !== $envLote) {
326
            throw DocumentsException::wrongDocument(
327
                5,
328
                "Os numeros de lote dos documentos são diferentes."
329
            );
330
        }
331
        return self::join(
332
            $ev->saveXML($event),
333
            $ret->saveXML($retEv),
334
            'procEventoNFe',
335
            $versao
336
        );
337
    }
338
339
    /**
340
     * Join the pieces of the source document with those of the answer
341
     * @param string $first
342
     * @param string $second
343
     * @param string $nodename
344
     * @param string $versao
345
     * @return string
346
     */
347
    protected static function join($first, $second, $nodename, $versao)
348
    {
349
        $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
350
                . "<$nodename versao=\"$versao\" "
351
                . "xmlns=\"".self::$urlPortal."\">";
352
        $xml .= $first;
353
        $xml .= $second;
354
        $xml .= "</$nodename>";
355
        return $xml;
356
    }
357
}
358