Completed
Push — master ( 857689...68fe75 )
by Roberto
14s
created

Tools::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1.125

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 2
cts 4
cp 0.5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 1.125
1
<?php
2
3
namespace NFePHP\CTe;
4
5
use NFePHP\Common\DateTime\DateTime;
6
use NFePHP\Common\Dom\Dom;
7
use NFePHP\Common\Dom\ValidXsd;
8
use NFePHP\Common\Exception;
9
use NFePHP\Common\LotNumber\LotNumber;
10
use NFePHP\Common\Strings\Strings;
11
use NFePHP\CTe\Auxiliar\IdentifyCTe;
12
use NFePHP\CTe\Auxiliar\Response;
13
14
/**
15
 * Classe principal para a comunicação com a SEFAZ
16
 *
17
 * @category  Library
18
 * @package   nfephp-org/sped-cte
19
 * @copyright 2009-2016 NFePHP
20
 * @license   http://www.gnu.org/licenses/lesser.html LGPL v3
21
 * @link      http://github.com/nfephp-org/sped-cte for the canonical source repository
22
 * @author    Roberto L. Machado <linux.rlm at gmail dot com>
23
 *
24
 *        CONTRIBUIDORES (em ordem alfabetica):
25
 *
26
 *          Maison K. Sakamoto <maison.sakamoto at gmail do com>
27
 *          Samuel M Basso <samuelbasso at gmail do com>
28
 */
29
class Tools extends BaseTools
30
{
31
    /**
32
     * urlPortal
33
     * Instância do WebService
34
     *
35
     * @var string
36
     */
37
    protected $urlPortal = 'http://www.portalfiscal.inf.br/cte';
38
39
    /**
40
     * aLastRetEvent
41
     *
42
     * @var array
43
     */
44
    private $aLastRetEvent = array();
45
46
    /**
47
     * @var string
48
     */
49
    public $erros = array();
50
51
    /**
52
     * modelo 57 (CTE-e) é um documento fiscal eletrônico,
53
     * instituído pelo AJUSTE SINIEF 09/07 (25/10/2007)
54
     * @var modelo
55
     */
56
    protected $modelo = '57';
57
58
    /**
59
     * @var string
60
     */
61
    protected $rootDir;
62
63
    public static $PL_CTE_200 = 'PL_CTe_200';
64
65
    public static $PL_CTE_300 = 'PL_CTe_300';
66
67 3
    public function __construct($configJson = '')
68
    {
69 3
        parent::__construct($configJson);
70
        $this->rootDir = dirname(__DIR__);
71
    }
72
73
    /**
74
     * assina
75
     *
76
     * @param  string  $xml
77
     * @param  boolean $saveFile
78
     * @return string
79
     * @throws Exception\RuntimeException
80
     */
81
    public function assina($xml = '', $saveFile = false)
82
    {
83
        return $this->assinaDoc($xml, 'cte', 'infCte', $saveFile);
84
    }
85
86
    /**
87
     * Transmite o xml para a sefaz
88
     * @param string|array $aXml
89
     * @param string $tpAmb
90
     * @param string $idLote
91
     * @param array $aRetorno
92
     * @param int $indSinc
93
     * @param boolean $compactarZip
94
     * @return string
95
     * @throws Exception\InvalidArgumentException
96
     * @throws Exception\RuntimeException
97
     */
98
    public function sefazEnvia(
99
        $aXml,
100
        $tpAmb = '2',
101
        $idLote = '',
102
        &$aRetorno = array(),
103
        $indSinc = 0,
0 ignored issues
show
Unused Code introduced by
The parameter $indSinc is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
104
        $compactarZip = false
0 ignored issues
show
Unused Code introduced by
The parameter $compactarZip is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
105
    ) {
106
        $sxml = $aXml;
107
        if (empty($aXml)) {
108
            $msg = "Pelo menos uma CTe deve ser informada.";
109
            throw new Exception\InvalidArgumentException($msg);
110
        }
111
        if (is_array($aXml)) {
112
            if (count($aXml) > 1) {
113
                //multiplas cte, não pode ser sincrono
114
                $indSinc = 0;
0 ignored issues
show
Unused Code introduced by
$indSinc is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
115
            }
116
            $sxml = implode("", $sxml);
117
        }
118
        $sxml = preg_replace("/<\?xml.*\?>/", "", $sxml);
119
        $siglaUF = $this->aConfig['siglaUF'];
120
121
        if ($tpAmb == '') {
122
            $tpAmb = $this->aConfig['tpAmb'];
123
        }
124
        if ($idLote == '') {
125
            $idLote = LotNumber::geraNumLote(15);
126
        }
127
        //carrega serviço
128
        $servico = 'CteRecepcao';
129
        $this->zLoadServico(
130
            'cte',
131
            $servico,
132
            $siglaUF,
133
            $tpAmb
134
        );
135
136
        if ($this->urlService == '') {
137
            $msg = "O envio de lote não está disponível na SEFAZ $siglaUF!!!";
138
            throw new Exception\RuntimeException($msg);
139
        }
140
141
        // Montagem dos dados da mensagem SOAP
142
        $dados = "<cteDadosMsg xmlns=\"$this->urlNamespace\">"
143
            . "<enviCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
144
            . "<idLote>$idLote</idLote>"
145
            . "$sxml"
146
            . "</enviCTe>"
147
            . "</cteDadosMsg>";
148
        // Envia dados via SOAP
149
        $retorno = $this->oSoap->send(
150
            $this->urlService,
151
            $this->urlNamespace,
152
            $this->urlHeader,
153
            $dados,
154
            $this->urlMethod
155
        );
156
157
        $lastMsg = $this->oSoap->lastMsg;
158
        $this->soapDebug = $this->oSoap->soapDebug;
0 ignored issues
show
Bug introduced by
The property soapDebug does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
159
        //salva mensagens
160
        $filename = "$idLote-enviCTe.xml";
161
        $this->zGravaFile('cte', $tpAmb, $filename, $lastMsg);
162
        $filename = "$idLote-retEnviCTe.xml";
163
        $this->zGravaFile('cte', $tpAmb, $filename, $retorno);
164
        //tratar dados de retorno
165
166
        $aRetorno = Response::readReturnSefaz($servico, $retorno);
167
        //caso o envio seja recebido com sucesso mover a CTe da pasta
168
        //das assinadas para a pasta das enviadas
169
        return (string) $retorno;
170
    }
171
172
    /**
173
     * Consulta o recibo na sefaz
174
     *
175
     * @param type $recibo
176
     * @param type $tpAmb
177
     * @param type $aRetorno
178
     * @return type
179
     * @throws Exception\InvalidArgumentException
180
     * @throws Exception\RuntimeException
181
     */
182 2
    public function sefazConsultaRecibo($recibo = '', $tpAmb = '2', &$aRetorno = array())
183
    {
184
        if ($recibo == '') {
185
            $msg = "Deve ser informado um recibo.";
186
            throw new Exception\InvalidArgumentException($msg);
187
        }
188
        if ($tpAmb == '') {
189
            $tpAmb = $this->aConfig['tpAmb'];
190
        }
191
        $siglaUF = $this->aConfig['siglaUF'];
192
        //carrega serviço
193
        $servico = 'CteRetRecepcao';
194
        $this->zLoadServico(
195
            'cte',
196
            $servico,
197
            $siglaUF,
198
            $tpAmb
199
        );
200
        if ($this->urlService == '') {
201
            $msg = "A consulta de CTe não está disponível na SEFAZ $siglaUF!!!";
202
            throw new Exception\RuntimeException($msg);
203
        }
204
        $cons = "<consReciCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
205
            . "<tpAmb>$tpAmb</tpAmb>"
206
            . "<nRec>$recibo</nRec>"
207
            . "</consReciCTe>";
208
        //montagem dos dados da mensagem SOAP
209
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$cons</cteDadosMsg>";
210
        //envia a solicitação via SOAP
211
        $retorno = $this->oSoap->send(
212
            $this->urlService,
213
            $this->urlNamespace,
214
            $this->urlHeader,
215 2
            $body,
216
            $this->urlMethod
217
        );
218
        $lastMsg = $this->oSoap->lastMsg;
219
        $this->soapDebug = $this->oSoap->soapDebug;
220
        //salva mensagens
221
        $filename = "$recibo-consReciCTe.xml";
222
        $this->zGravaFile('cte', $tpAmb, $filename, $lastMsg);
223
        $filename = "$recibo-retConsReciCTe.xml";
224
        $this->zGravaFile('cte', $tpAmb, $filename, $retorno);
225
        //tratar dados de retorno
226
        $aRetorno = Response::readReturnSefaz($servico, $retorno);
227
        //podem ser retornados nenhum, um ou vários protocolos
228
        //caso existam protocolos protocolar as CTe e movelas-las para a
229
        //pasta enviadas/aprovadas/anomes
230
        return (string) $retorno;
231
    }
232
233
    /**
234
     * consulta a chave de acesso do CT-e
235
     *
236
     * @param type $chave
237
     * @param type $tpAmb
238
     * @param type $aRetorno
239
     * @return type
240
     * @throws Exception\InvalidArgumentException
241
     * @throws Exception\RuntimeException
242
     */
243
    public function sefazConsultaChave($chave = '', $tpAmb = '2', &$aRetorno = array())
244
    {
245
        $chCTe = preg_replace('/[^0-9]/', '', $chave);
246
        if (strlen($chCTe) != 44) {
247
            $msg = "Uma chave de 44 dígitos da CTe deve ser passada.";
248
            throw new Exception\InvalidArgumentException($msg);
249
        }
250
        if ($tpAmb == '') {
251
            $tpAmb = $this->aConfig['tpAmb'];
252
        }
253
        $cUF = substr($chCTe, 0, 2);
254
        $siglaUF = $this->zGetSigla($cUF);
255
        //carrega serviço
256
        $servico = 'CteConsultaProtocolo';
257
        $this->zLoadServico(
258
            'cte',
259
            $servico,
260
            $siglaUF,
261
            $tpAmb
262
        );
263
        if ($this->urlService == '') {
264
            $msg = "A consulta de CTe não está disponível na SEFAZ $siglaUF!!!";
265
            throw new Exception\RuntimeException($msg);
266
        }
267
        $cons = "<consSitCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
268
            . "<tpAmb>$tpAmb</tpAmb>"
269
            . "<xServ>CONSULTAR</xServ>"
270
            . "<chCTe>$chCTe</chCTe>"
271
            . "</consSitCTe>";
272
        //montagem dos dados da mensagem SOAP
273
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$cons</cteDadosMsg>";
274
        //envia a solicitação via SOAP
275
        $retorno = $this->oSoap->send(
276
            $this->urlService,
277
            $this->urlNamespace,
278
            $this->urlHeader,
279
            $body,
280
            $this->urlMethod
281
        );
282
        $lastMsg = $this->oSoap->lastMsg;
283
        $this->soapDebug = $this->oSoap->soapDebug;
284
        //salva mensagens
285
        $filename = "$chCTe-consSitCTe.xml";
286
        $this->zGravaFile('cte', $tpAmb, $filename, $lastMsg);
287
        $filename = "$chCTe-retConsSitCTe.xml";
288
        $this->zGravaFile('cte', $tpAmb, $filename, $retorno);
289
        //tratar dados de retorno
290
        $aRetorno = Response::readReturnSefaz($servico, $retorno);
291
        return (string) $retorno;
292
    }
293
294
    /**
295
     * consulta disponibilidade do serviço web service da sefaz
296
     *
297
     * @param type $siglaUF
298
     * @param type $tpAmb
299
     * @param type $aRetorno
300
     * @return type
301
     * @throws Exception\RuntimeException
302
     */
303
    public function sefazStatus($siglaUF = '', $tpAmb = '2', &$aRetorno = array())
304
    {
305
        if ($tpAmb == '') {
306
            $tpAmb = $this->aConfig['tpAmb'];
307
        }
308
        if ($siglaUF == '') {
309
            $siglaUF = $this->aConfig['siglaUF'];
310
        }
311
        //carrega serviço
312
        $servico = 'CteStatusServico';
313
        $this->zLoadServico(
314
            'cte',
315
            $servico,
316
            $siglaUF,
317
            $tpAmb
318
        );
319
        if ($this->urlService == '') {
320
            $msg = "O status não está disponível na SEFAZ $siglaUF!!!";
321
            throw new Exception\RuntimeException($msg);
322
        }
323
        $cons = "<consStatServCte xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
324
            . "<tpAmb>$tpAmb</tpAmb>"
325
            . "<xServ>STATUS</xServ></consStatServCte>";
326
        //montagem dos dados da mensagem SOAP
327
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$cons</cteDadosMsg>";
328
        //consome o webservice e verifica o retorno do SOAP
329
        $retorno = $this->oSoap->send(
330
            $this->urlService,
331
            $this->urlNamespace,
332
            $this->urlHeader,
333
            $body,
334
            $this->urlMethod
335
        );
336
        $lastMsg = $this->oSoap->lastMsg;
337
        $this->soapDebug = $this->oSoap->soapDebug;
338
        $datahora = date('Ymd_His');
339
        $filename = $siglaUF."_"."$datahora-consStatServCte.xml";
340
        $this->zGravaFile('cte', $tpAmb, $filename, $lastMsg);
341
        $filename = $siglaUF."_"."$datahora-retConsStatServCte.xml";
342
        $this->zGravaFile('cte', $tpAmb, $filename, $retorno);
343
        //tratar dados de retorno
344
        $aRetorno = Response::readReturnSefaz($servico, $retorno);
345
        return (string) $retorno;
346
    }
347
348
    /**
349
     * Inutiza sequencia de numeracao
350
     *
351
     * @param int $nSerie
352
     * @param int $nIni
353
     * @param int $nFin
354
     * @param string $xJust
355
     * @param int $tpAmb
356
     * @param array $aRetorno
357
     * @return string
358
     * @throws Exception\RuntimeException
359
     * @throws Exception\InvalidArgumentException
360
     */
361
    public function sefazInutiliza(
362
        $nSerie = '1',
363
        $nIni = '',
364
        $nFin = '',
365
        $xJust = '',
366
        $tpAmb = '2',
367
        &$aRetorno = array(),
368
        $salvarMensagens = true
369
    ) {
370
        $nSerie = (integer) $nSerie;
371
        $nIni = (integer) $nIni;
372
        $nFin = (integer) $nFin;
373
        $xJust = Strings::cleanString($xJust);
374
        //Função comentada por não estar implementada.
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
375
//        $this->zValidParamInut($xJust, $nSerie, $nIni, $nFin);
376
        if ($tpAmb == '') {
377
            $tpAmb = $this->aConfig['tpAmb'];
378
        }
379
        // Identificação do serviço
380
        $servico = 'CteInutilizacao';
381
        //monta serviço
382
        $siglaUF = $this->aConfig['siglaUF'];
383
        //carrega serviço
384
        $this->zLoadServico(
385
            'cte',
386
            $servico,
387
            $siglaUF,
388
            $tpAmb
389
        );
390
        if ($this->urlService == '') {
391
            $msg = "A inutilização não está disponível na SEFAZ $siglaUF!!!";
392
            throw new Exception\RuntimeException($msg);
393
        }
394
        //montagem dos dados da mensagem SOAP
395
        $cnpj = $this->aConfig['cnpj'];
396
        $sAno = (string) date('y');
397
        $sSerie = str_pad($nSerie, 3, '0', STR_PAD_LEFT);
398
        $sInicio = str_pad($nIni, 9, '0', STR_PAD_LEFT);
399
        $sFinal = str_pad($nFin, 9, '0', STR_PAD_LEFT);
400
        //limpa os caracteres indesejados da justificativa
401
        $xJust = Strings::cleanString($xJust);
402
        // Identificador da TAG a ser assinada formada com Código da UF +
403
        // precedida do literal “ID”
404
        // 41 posições
405
        $id = 'ID'.$this->urlcUF.$cnpj.'57'.$sSerie.$sInicio.$sFinal;
406
        // Montagem do corpo da mensagem
407
        $dXML = "<inutCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
408
            ."<infInut Id=\"$id\">"
409
            ."<tpAmb>$tpAmb</tpAmb>"
410
            ."<xServ>INUTILIZAR</xServ>"
411
            ."<cUF>$this->urlcUF</cUF>"
412
            ."<ano>$sAno</ano>"
413
            ."<CNPJ>$cnpj</CNPJ>"
414
            ."<mod>57</mod>"
415
            ."<serie>$nSerie</serie>"
416
            ."<nCTIni>$nIni</nCTIni>"
417
            ."<nCTFin>$nFin</nCTFin>"
418
            ."<xJust>$xJust</xJust>"
419
            ."</infInut></inutCTe>";
420
        //assina a solicitação de inutilização
421
        $signedMsg = $this->oCertificate->signXML($dXML, 'infInut');
422
        $signedMsg = Strings::clearXml($signedMsg, true);
423
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$signedMsg</cteDadosMsg>";
424
        //envia a solicitação via SOAP
425
        $retorno = $this->oSoap->send(
426
            $this->urlService,
427
            $this->urlNamespace,
428
            $this->urlHeader,
429
            $body,
430
            $this->urlMethod
431
        );
432
        $lastMsg = $this->oSoap->lastMsg;
433
        $this->soapDebug = $this->oSoap->soapDebug;
434
        //salva mensagens
435
        if ($salvarMensagens) {
436
            $filename = "$sAno-$this->modelo-$sSerie-".$sInicio."_".$sFinal."-inutCTe.xml";
437
            $this->zGravaFile('cte', $tpAmb, $filename, $lastMsg);
438
            $filename = "$sAno-$this->modelo-$sSerie-".$sInicio."_".$sFinal."-retInutCTe.xml";
439
            $this->zGravaFile('cte', $tpAmb, $filename, $retorno);
440
        }
441
        //tratar dados de retorno
442
        $aRetorno = Response::readReturnSefaz($servico, $retorno);
443
        //Comentado por não ter implementada a função de zAddProtMsg
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
444
//        if ($aRetorno['cStat'] == '102') {
445
//            $retorno = $this->zAddProtMsg('ProcInutCTe', 'inutCTe', $signedMsg, 'retInutCTe', $retorno);
446
        if ($salvarMensagens) {
447
            $filename = "$sAno-$this->modelo-$sSerie-".$sInicio."_".$sFinal."-procInutCTe.xml";
448
            $this->zGravaFile('cte', $tpAmb, $filename, $retorno, 'inutilizadas');
449
        }
450
//        }
451
        return (string) $retorno;
452
    }
453
454
    /**
455
     * Cancelamento de numero CT-e
456
     *
457
     * @param type $chCTe
458
     * @param type $tpAmb
459
     * @param type $xJust
460
     * @param type $nProt
461
     * @param type $aRetorno
462
     * @return type
463
     * @throws Exception\InvalidArgumentException
464
     */
465
    public function sefazCancela($chCTe = '', $tpAmb = '2', $xJust = '', $nProt = '', &$aRetorno = array())
466
    {
467
        $chCTe = preg_replace('/[^0-9]/', '', $chCTe);
468
        $nProt = preg_replace('/[^0-9]/', '', $nProt);
469
        $xJust = Strings::cleanString($xJust);
470
        //validação dos dados de entrada
471
        if (strlen($chCTe) != 44) {
472
            $msg = "Uma chave de CTe válida não foi passada como parâmetro $chCTe.";
473
            throw new Exception\InvalidArgumentException($msg);
474
        }
475
        if ($nProt == '') {
476
            $msg = "Não foi passado o numero do protocolo!!";
477
            throw new Exception\InvalidArgumentException($msg);
478
        }
479
        if (strlen($xJust) < 15 || strlen($xJust) > 255) {
480
            $msg = "A justificativa deve ter pelo menos 15 digitos e no máximo 255!!";
481
            throw new Exception\InvalidArgumentException($msg);
482
        }
483
        $siglaUF = $this->zGetSigla(substr($chCTe, 0, 2));
484
485
        //estabelece o codigo do tipo de evento CANCELAMENTO
486
        $tpEvento = '110111';
487
        $descEvento = 'Cancelamento';
488
        $nSeqEvento = 1;
489
        //monta mensagem
490
        $tagAdic = "<evCancCTe>"
491
            . "<descEvento>$descEvento</descEvento>"
492
            . "<nProt>$nProt</nProt>"
493
            . "<xJust>$xJust</xJust>"
494
            . "</evCancCTe>";
495
        $retorno = $this->zSefazEvento($siglaUF, $chCTe, $tpAmb, $tpEvento, $nSeqEvento, $tagAdic);
0 ignored issues
show
Bug introduced by
It seems like $chCTe defined by preg_replace('/[^0-9]/', '', $chCTe) on line 467 can also be of type array<integer,string>; however, NFePHP\CTe\Tools::zSefazEvento() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
496
        $aRetorno = $this->aLastRetEvent;
497
        return $retorno;
498
    }
499
500
    public function enviaMail($pathXml = '', $aMails = array(), $templateFile = '', $comPdf = false, $pathPdf = '')
0 ignored issues
show
Unused Code introduced by
The parameter $templateFile is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
501
    {
502
        $mail = new Mail($this->aMailConf);
503
        // Se não for informado o caminho do PDF, monta um através do XML
504
        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
505
        if ($comPdf && $this->modelo == '55' && $pathPdf == '') {
506
            $docxml = Files\FilesFolders::readFile($pathXml);
507
            $danfe = new Extras\Danfe($docxml, 'P', 'A4', $this->aDocFormat['pathLogoFile'], 'I', '');
508
            $id = $danfe->montaDANFE();
509
            $pathPdf = $this->aConfig['pathNFeFiles']
510
                . DIRECTORY_SEPARATOR
511
                . $this->ambiente
512
                . DIRECTORY_SEPARATOR
513
                . 'pdf'
514
                . DIRECTORY_SEPARATOR
515
                . $id . '-danfe.pdf';
516
            $pdf = $danfe->printDANFE($pathPdf, 'F');
517
        }
518
         *
519
         */
520
        if ($mail->envia($pathXml, $aMails, $comPdf, $pathPdf) === false) {
521
            throw new Exception\RuntimeException('Email não enviado. '.$mail->error);
522
        }
523
        return true;
524
    }
525
526
    /**
527
     * zSefazEvento
528
     *
529
     * @param    string $siglaUF
530
     * @param    string $chCTe
531
     * @param    string $tpAmb
532
     * @param    string $tpEvento
533
     * @param    string $nSeqEvento
534
     * @param    string $tagAdic
535
     * @return   string
536
     * @throws   Exception\RuntimeException
537
     * @internal function zLoadServico (Common\Base\BaseTools)
538
     */
539
    protected function zSefazEvento(
540
        $siglaUF = '',
541
        $chCTe = '',
542
        $tpAmb = '2',
543
        $tpEvento = '',
544
        $nSeqEvento = '1',
545
        $tagAdic = ''
546
    ) {
547
        if ($tpAmb == '') {
548
            $tpAmb = $this->aConfig['tpAmb'];
549
        }
550
        //carrega serviço
551
        $servico = 'CteRecepcaoEvento';
552
        $this->zLoadServico(
553
            'cte',
554
            $servico,
555
            $siglaUF,
556
            $tpAmb
557
        );
558
        if ($this->urlService == '') {
559
            $msg = "A recepção de eventos não está disponível na SEFAZ $siglaUF!!!";
560
            throw new Exception\RuntimeException($msg);
561
        }
562
        $aRet = $this->zTpEv($tpEvento);
563
        $aliasEvento = $aRet['alias'];
564
        $descEvento = $aRet['desc'];
0 ignored issues
show
Unused Code introduced by
$descEvento is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
565
        $cnpj = $this->aConfig['cnpj'];
566
        $dhEvento = DateTime::convertTimestampToSefazTime(time());
567
        $sSeqEvento = str_pad($nSeqEvento, 2, "0", STR_PAD_LEFT);
568
        $eventId = "ID".$tpEvento.$chCTe.$sSeqEvento;
569
        $cOrgao = $this->urlcUF;
570
        if ($siglaUF == 'AN') {
571
            $cOrgao = '91';
572
        }
573
        $mensagem = "<infEvento Id=\"$eventId\">"
574
            . "<cOrgao>$cOrgao</cOrgao>"
575
            . "<tpAmb>$tpAmb</tpAmb>"
576
            . "<CNPJ>$cnpj</CNPJ>"
577
            . "<chCTe>$chCTe</chCTe>"
578
            . "<dhEvento>$dhEvento</dhEvento>"
579
            . "<tpEvento>$tpEvento</tpEvento>"
580
            . "<nSeqEvento>$nSeqEvento</nSeqEvento>"
581
            . "<detEvento versaoEvento=\"$this->urlVersion\">"
582
            . "$tagAdic"
583
            . "</detEvento>"
584
            . "</infEvento>";
585
586
        $cons = "<eventoCTe xmlns=\"$this->urlPortal\" versao=\"$this->urlVersion\">"
587
            . "$mensagem"
588
            . "</eventoCTe>";
589
590
        $signedMsg = $this->oCertificate->signXML($cons, 'infEvento');
591
        //limpa o xml
592
        $signedMsg = Strings::clearXml($signedMsg, true);
593
        //montagem dos dados da mensagem SOAP
594
        $body = "<cteDadosMsg xmlns=\"$this->urlNamespace\">$signedMsg</cteDadosMsg>";
595
596
        $retorno = $this->oSoap->send(
597
            $this->urlService,
598
            $this->urlNamespace,
599
            $this->urlHeader,
600
            $body,
601
            $this->urlMethod
602
        );
603
        $lastMsg = $this->oSoap->lastMsg;
604
        $this->soapDebug = $this->oSoap->soapDebug;
605
        //salva mensagens
606
        $filename = "$chCTe-$aliasEvento-envEvento.xml";
607
        $this->zGravaFile('cte', $tpAmb, $filename, $lastMsg);
608
        $filename = "$chCTe-$aliasEvento-retEnvEvento.xml";
609
        $this->zGravaFile('cte', $tpAmb, $filename, $retorno);
610
        //tratar dados de retorno
611
        $this->aLastRetEvent = Response::readReturnSefaz($servico, $retorno);
612
        if ($this->aLastRetEvent['cStat'] == '134' ||
613
                $this->aLastRetEvent['cStat'] == '135' ||
614
                $this->aLastRetEvent['cStat'] == '136') {
615
            $pasta = 'eventos'; //default
616
            if ($aliasEvento == 'CancCTe') {
617
                $pasta = 'canceladas';
618
                $filename = "$chCTe-$aliasEvento-procEvento.xml";
619
            } elseif ($aliasEvento == 'CCe') {
620
                $pasta = 'cartacorrecao';
621
                $filename = "$chCTe-$aliasEvento-$nSeqEvento-procEvento.xml";
622
            }
623
            $retorno = $this->zAddProtMsg('procEventoCTe', 'eventoCTe', $signedMsg, 'retEventoCTe', $retorno);
624
            $this->zGravaFile('cte', $tpAmb, $filename, $retorno, $pasta);
625
        }
626
        return (string) $retorno;
627
    }
628
629
    /**
630
     * zAddProtMsg
631
     *
632
     * @param  string $tagproc
633
     * @param  string $tagmsg
634
     * @param  string $xmlmsg
635
     * @param  string $tagretorno
636
     * @param  string $xmlretorno
637
     * @return string
638
     */
639
    protected function zAddProtMsg($tagproc, $tagmsg, $xmlmsg, $tagretorno, $xmlretorno)
640
    {
641
        $doc = new Dom();
642
        $doc->loadXMLString($xmlmsg);
643
        $nodedoc = $doc->getNode($tagmsg, 0);
644
        $procver = $nodedoc->getAttribute("versao");
645
        $procns = $nodedoc->getAttribute("xmlns");
646
647
        $doc1 = new Dom();
648
        $doc1->loadXMLString($xmlretorno);
649
        $nodedoc1 = $doc1->getNode($tagretorno, 0);
650
651
        $proc = new \DOMDocument('1.0', 'utf-8');
652
        $proc->formatOutput = false;
653
        $proc->preserveWhiteSpace = false;
654
        //cria a tag nfeProc
655
        $procNode = $proc->createElement($tagproc);
656
        $proc->appendChild($procNode);
657
        //estabele o atributo de versão
658
        $procNodeAtt1 = $procNode->appendChild($proc->createAttribute('versao'));
659
        $procNodeAtt1->appendChild($proc->createTextNode($procver));
660
        //estabelece o atributo xmlns
661
        $procNodeAtt2 = $procNode->appendChild($proc->createAttribute('xmlns'));
662
        $procNodeAtt2->appendChild($proc->createTextNode($procns));
663
        //inclui a tag inutNFe
664
        $node = $proc->importNode($nodedoc, true);
665
        $procNode->appendChild($node);
666
        //inclui a tag retInutNFe
667
        $node = $proc->importNode($nodedoc1, true);
668
        $procNode->appendChild($node);
669
        //salva o xml como string em uma variável
670
        $procXML = $proc->saveXML();
671
        //remove as informações indesejadas
672
        $procXML = Strings::clearProt($procXML);
673
        return $procXML;
674
    }
675
676
    /**
677
     * zTpEv
678
     *
679
     * @param  string $tpEvento
680
     * @return array
681
     * @throws Exception\RuntimeException
682
     */
683
    private function zTpEv($tpEvento = '')
684
    {
685
        //montagem dos dados da mensagem SOAP
686
        switch ($tpEvento) {
687
            case '110110':
688
                //CCe
689
                $aliasEvento = 'CCe';
690
                $descEvento = 'Carta de Correcao';
691
                break;
692
            case '110111':
693
                //cancelamento
694
                $aliasEvento = 'CancCTe';
695
                $descEvento = 'Cancelamento';
696
                break;
697
            case '110140':
698
                //EPEC
699
                //emissão em contingência EPEC
700
                $aliasEvento = 'EPEC';
701
                $descEvento = 'EPEC';
702
                break;
703
            case '111500':
704
            case '111501':
705
                //EPP
706
                //Pedido de prorrogação
707
                $aliasEvento = 'EPP';
708
                $descEvento = 'Pedido de Prorrogacao';
709
                break;
710
            case '111502':
711
            case '111503':
712
                //ECPP
713
                //Cancelamento do Pedido de prorrogação
714
                $aliasEvento = 'ECPP';
715
                $descEvento = 'Cancelamento de Pedido de Prorrogacao';
716
                break;
717
            case '210200':
718
                //Confirmacao da Operacao
719
                $aliasEvento = 'EvConfirma';
720
                $descEvento = 'Confirmacao da Operacao';
721
                break;
722
            case '210210':
723
                //Ciencia da Operacao
724
                $aliasEvento = 'EvCiencia';
725
                $descEvento = 'Ciencia da Operacao';
726
                break;
727
            case '210220':
728
                //Desconhecimento da Operacao
729
                $aliasEvento = 'EvDesconh';
730
                $descEvento = 'Desconhecimento da Operacao';
731
                break;
732
            case '210240':
733
                //Operacao não Realizada
734
                $aliasEvento = 'EvNaoRealizada';
735
                $descEvento = 'Operacao nao Realizada';
736
                break;
737
            default:
738
                $msg = "O código do tipo de evento informado não corresponde a "
739
                    . "nenhum evento estabelecido.";
740
                throw new Exception\RuntimeException($msg);
741
        }
742
        return array('alias' => $aliasEvento, 'desc' => $descEvento);
743
    }
744
745
    /**
746
     * validarXml
747
     * Valida qualquer xml do sistema CTe com seu xsd
748
     * NOTA: caso não exista um arquivo xsd apropriado retorna false
749
     *
750
     * @param  string $xml path ou conteudo do xml
751
     * @return boolean
752
     */
753
    public function validarXml($xml = '')
754
    {
755
        $aResp = array();
756
        $schem = IdentifyCTe::identificar($xml, $aResp);
757
        if ($schem == '') {
758
            $this->erros[] = "Não foi possível identificar o documento";
759
            return false;
760
        }
761
        $xsdFile = $aResp['Id'].'_v'.$aResp['versao'].'.xsd';
762
        $xsdPath = $this->rootDir.DIRECTORY_SEPARATOR .
763
            'schemas' .
764
            DIRECTORY_SEPARATOR .
765
            $this->aConfig['schemasCTe'] .
766
            DIRECTORY_SEPARATOR .
767
            $xsdFile;
768
        if (! is_file($xsdPath)) {
769
            $this->erros[] = "O arquivo XSD $xsdFile não foi localizado.";
770
            return false;
771
        }
772
        if (! ValidXsd::validar($aResp['xml'], $xsdPath)) {
773
            $this->erros[] = ValidXsd::$errors;
774
            return false;
775
        }
776
        return true;
777
    }
778
779
    /**
780
     * Transmite a correção
781
     * conforme o MOC(Manual de Orientações do Contribuinte)
782
     * Art. 58-B Fica permitida a utilização de carta de correção,
783
     * para regularização de erro ocorrido na emissão de documentos
784
     * fiscais relativos à prestação de serviço de transporte, desde que o
785
     * erro não esteja relacionado com:
786
     * I - as variáveis que determinam o valor do imposto tais como:
787
     *  base de cálculo, alíquota, diferença de preço, quantidade, valor da prestação
788
     * II - a correção de dados cadastrais que implique mudança do emitente,
789
     *  tomador, remetente ou do destinatário;
790
     * III - a data de emissão ou de saída.
791
     *
792
     * @param string $chCTe
793
     * @param string $tpAmb
794
     * @param string $nSeqEvento
795
     * @param array $infCorrecao
796
     * @param array $aRetorno
797
     * @return string
798
     * @throws Exception\InvalidArgumentException
799
     */
800
    public function sefazCartaCorrecao(
801
        $chCTe = '',
802
        $tpAmb = '2',
803
        $nSeqEvento = '1',
804
        $infCorrecao = array(),
805
        &$aRetorno = array()
806
    ) {
807
        $chCTe = preg_replace('/[^0-9]/', '', $chCTe);
808
809
        //validação dos dados de entrada
810
        if (strlen($chCTe) != 44) {
811
            $msg = "Uma chave de CTe válida não foi passada como parâmetro $chCTe.";
812
            throw new Exception\InvalidArgumentException($msg);
813
        }
814
        if ($chCTe == '' || empty(array_filter($infCorrecao))) {
815
            $msg = "Preencha os campos obrigatórios!";
816
            throw new Exception\InvalidArgumentException($msg);
817
        }
818
        if ($tpAmb == '') {
819
            $tpAmb = $this->aConfig['tpAmb'];
820
        }
821
        $siglaUF = $this->zGetSigla(substr($chCTe, 0, 2));
822
823
        //estabelece o codigo do tipo de evento CARTA DE CORRECAO
824
        $tpEvento = '110110';
825
826
        //Grupo de Informações de Correção
827
        $correcoes = '';
828
        foreach ($infCorrecao as $info) {
829
            $correcoes .=
830
                "<infCorrecao>"
831
                    ."<grupoAlterado>".$info['grupoAlterado']."</grupoAlterado>"
832
                    ."<campoAlterado>".$info['campoAlterado']."</campoAlterado>"
833
                    ."<valorAlterado>".$info['valorAlterado']."</valorAlterado>"
834
                    ."<nroItemAlterado>".$info['nroItemAlterado']."</nroItemAlterado>"
835
                ."</infCorrecao>";
836
        }
837
        //monta mensagem
838
        $tagAdic = Tools::serializarMensagemDoEventoCartaDeCorrecao($infCorrecao);
839
        $retorno = $this->zSefazEvento($siglaUF, $chCTe, $tpAmb, $tpEvento, $nSeqEvento, $tagAdic);
840
        $aRetorno = $this->aLastRetEvent;
841
        return $retorno;
842
    }
843
844
    public function addProtocolo($pathCTeFile = '', $pathProtfile = '', $saveFile = false)
845
    {
846
        //carrega a CTe
847
        $docCte = new Dom();
848
849
        if (file_exists($pathCTeFile)) {
850
            //carrega o XML pelo caminho do arquivo informado
851
            $docCte->loadXMLFile($pathCTeFile);
852
        } else {
853
            //carrega o XML pelo conteúdo
854
            $docCte->loadXMLString($pathCTeFile);
855
        }
856
857
        $nodecte = $docCte->getNode('CTe', 0);
858
        if ($nodecte == '') {
859
            $msg = "O arquivo indicado como CTe não é um xml de CTe!";
860
            throw new Exception\RuntimeException($msg);
861
        }
862
        if ($docCte->getNode('Signature') == '') {
863
            $msg = "A CTe não está assinada!";
864
            throw new Exception\RuntimeException($msg);
865
        }
866
        //carrega o protocolo
867
        $docprot = new Dom();
868
869
        if (file_exists($pathProtfile)) {
870
            //carrega o XML pelo caminho do arquivo informado
871
            $docprot->loadXMLFile($pathProtfile);
872
        } else {
873
            //carrega o XML pelo conteúdo
874
            $docprot->loadXMLString($pathProtfile);
875
        }
876
877
        $nodeprots = $docprot->getElementsByTagName('protCTe');
878
        if ($nodeprots->length == 0) {
879
            $msg = "O arquivo indicado não contem um protocolo de autorização!";
880
            throw new Exception\RuntimeException($msg);
881
        }
882
        //carrega dados da CTe
883
        $tpAmb = $docCte->getNodeValue('tpAmb');
884
        $anomes = date(
885
            'Ym',
886
            DateTime::convertSefazTimeToTimestamp($docCte->getNodeValue('dhEmi'))
887
        );
888
//        $infCTe = $docCte->getNode("infCTe", 0);
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
889
//        $versao = $infCTe->getAttribute("versao");
890
//        $chaveId = $infCTe->getAttribute("Id");
891
//        $chaveCTe = preg_replace('/[^0-9]/', '', $chaveId);
892
        $digValueCTe = $docCte->getNodeValue('DigestValue');
893
        //carrega os dados do protocolo
894
        for ($i = 0; $i < $nodeprots->length; $i++) {
895
            $nodeprot = $nodeprots->item($i);
896
            $protver = $nodeprot->getAttribute("versao");
897
            $chaveProt = $nodeprot->getElementsByTagName("chCTe")->item(0)->nodeValue;
898
            $digValueProt = ($nodeprot->getElementsByTagName("digVal")->length)
899
                ? $nodeprot->getElementsByTagName("digVal")->item(0)->nodeValue
900
                : '';
901
            $infProt = $nodeprot->getElementsByTagName("infProt")->item(0);
902
//            if ($digValueCTe == $digValueProt && $chaveCTe == $chaveProt) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
903
//                break;
904
//            }
905
        }
906
        if ($digValueCTe != $digValueProt) {
0 ignored issues
show
Bug introduced by
The variable $digValueProt does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
907
            $msg = "Inconsistência! O DigestValue da CTe não combina com o do digVal do protocolo indicado!";
908
            throw new Exception\RuntimeException($msg);
909
        }
910
//        if ($chaveCTe != $chaveProt) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
49% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
911
//            $msg = "O protocolo indicado pertence a outra CTe. Os números das chaves não combinam !";
912
//            throw new Exception\RuntimeException($msg);
913
//        }
914
        //cria a CTe processada com a tag do protocolo
915
        $procCte = new \DOMDocument('1.0', 'utf-8');
916
        $procCte->formatOutput = false;
917
        $procCte->preserveWhiteSpace = false;
918
        //cria a tag cteProc
919
        $cteProc = $procCte->createElement('cteProc');
920
        $procCte->appendChild($cteProc);
921
        //estabele o atributo de versão
922
        $cteProcAtt1 = $cteProc->appendChild($procCte->createAttribute('versao'));
923
        $cteProcAtt1->appendChild($procCte->createTextNode($protver));
0 ignored issues
show
Bug introduced by
The variable $protver does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
924
        //estabelece o atributo xmlns
925
        $cteProcAtt2 = $cteProc->appendChild($procCte->createAttribute('xmlns'));
926
        $cteProcAtt2->appendChild($procCte->createTextNode($this->urlPortal));
927
        //inclui a tag CTe
928
        $node = $procCte->importNode($nodecte, true);
929
        $cteProc->appendChild($node);
930
        //cria tag protCTe
931
        $protCTe = $procCte->createElement('protCTe');
932
        $cteProc->appendChild($protCTe);
933
        //estabele o atributo de versão
934
        $protCTeAtt1 = $protCTe->appendChild($procCte->createAttribute('versao'));
935
        $protCTeAtt1->appendChild($procCte->createTextNode($protver));
936
        //cria tag infProt
937
        $nodep = $procCte->importNode($infProt, true);
0 ignored issues
show
Bug introduced by
The variable $infProt does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
938
        $protCTe->appendChild($nodep);
939
        //salva o xml como string em uma variável
940
        $procXML = $procCte->saveXML();
941
        //remove as informações indesejadas
942
        $procXML = Strings::clearProt($procXML);
943
        if ($saveFile) {
944
//            $filename = "{$chaveCTe}-protCTe.xml";
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
945
            $filename = "{$chaveProt}-protCTe.xml";
0 ignored issues
show
Bug introduced by
The variable $chaveProt does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
946
            $this->zGravaFile(
947
                'cte',
948
                $tpAmb,
949
                $filename,
950
                $procXML,
951
                'enviadas'.DIRECTORY_SEPARATOR.'aprovadas',
952
                $anomes
953
            );
954
        }
955
        return $procXML;
956
    }
957
958
959
    /**
960
     * addCancelamento
961
     * Adiciona a tga de cancelamento a uma CTe já autorizada
962
     * NOTA: não é requisito da SEFAZ, mas auxilia na identificação das CTe que foram canceladas
963
     * @param string $pathCTefile
964
     * @param string $pathCancfile
965
     * @param bool $saveFile
966
     * @return string
967
     * @throws Exception\RuntimeException
968
     */
969
    public function addCancelamento($pathCTefile = '', $pathCancfile = '', $saveFile = false)
970
    {
971
        $procXML = '';
972
        //carrega a CTe
973
        $docCTe = new Dom();
974
        
975
        if (file_exists($pathCTefile)) {
976
            //carrega o XML pelo caminho do arquivo informado
977
            $docCTe->loadXMLFile($pathCTefile);
978
        } else {
979
            //carrega o XML pelo conteúdo
980
            $docCTe->loadXMLString($pathCTefile);
981
        }
982
        
983
        $nodeCTe = $docCTe->getNode('CTe', 0);
984
        if ($nodeCTe == '') {
985
            $msg = "O arquivo indicado como CTe não é um xml de CTe!";
986
            throw new Exception\RuntimeException($msg);
987
        }
988
        $proCTe = $docCTe->getNode('protCTe');
989
        if ($proCTe == '') {
990
            $msg = "A CTe não está protocolada ainda!!";
991
            throw new Exception\RuntimeException($msg);
992
        }
993
        $chaveCTe = $proCTe->getElementsByTagName('chCTe')->item(0)->nodeValue;
994
        //$nProtCTe = $proCTe->getElementsByTagName('nProt')->item(0)->nodeValue;
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
995
        $tpAmb = $docCTe->getNodeValue('tpAmb');
0 ignored issues
show
Unused Code introduced by
$tpAmb is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
996
        $anomes = date(
997
            'Ym',
998
            DateTime::convertSefazTimeToTimestamp($docCTe->getNodeValue('dhEmi'))
999
        );
1000
        //carrega o cancelamento
1001
        //pode ser um evento ou resultado de uma consulta com multiplos eventos
1002
        $doccanc = new Dom();
1003
        
1004
        if (file_exists($pathCancfile)) {
1005
            //carrega o XML pelo caminho do arquivo informado
1006
            $doccanc->loadXMLFile($pathCancfile);
1007
        } else {
1008
            //carrega o XML pelo conteúdo
1009
            $doccanc->loadXMLString($pathCancfile);
1010
        }
1011
        $retEvento = $doccanc->getElementsByTagName('retEventoCTe')->item(0);
1012
        $eventos = $retEvento->getElementsByTagName('infEvento');
1013
        foreach ($eventos as $evento) {
1014
            //evento
1015
            $cStat = $evento->getElementsByTagName('cStat')->item(0)->nodeValue;
1016
            $tpAmb = $evento->getElementsByTagName('tpAmb')->item(0)->nodeValue;
1017
            $chaveEvento = $evento->getElementsByTagName('chCTe')->item(0)->nodeValue;
1018
            $tpEvento = $evento->getElementsByTagName('tpEvento')->item(0)->nodeValue;
1019
            //$nProtEvento = $evento->getElementsByTagName('nProt')->item(0)->nodeValue;
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1020
            //verifica se conferem os dados
1021
            //cStat = 135 ==> evento homologado
1022
            //cStat = 136 ==> vinculação do evento à respectiva NF-e prejudicada
1023
            //cStat = 155 ==> Cancelamento homologado fora de prazo
1024
            //tpEvento = 110111 ==> Cancelamento
1025
            //chave do evento == chave da CTe
1026
            //protocolo do evneto ==  protocolo da CTe
1027
            if (($cStat == '135' || $cStat == '136' || $cStat == '155') &&
1028
                $tpEvento == '110111' &&
1029
                $chaveEvento == $chaveCTe
1030
            ) {
1031
                $proCTe->getElementsByTagName('cStat')->item(0)->nodeValue = '101';
1032
                $proCTe->getElementsByTagName('xMotivo')->item(0)->nodeValue = 'Cancelamento de CT-e homologado';
1033
                $procXML = $docCTe->saveXML();
1034
                //remove as informações indesejadas
1035
                $procXML = Strings::clearProt($procXML);
1036
                if ($saveFile) {
1037
                    $filename = "$chaveCTe-protCTe.xml";
1038
                    $this->zGravaFile(
1039
                        'cte',
1040
                        $tpAmb,
1041
                        $filename,
1042
                        $procXML,
1043
                        'canceladas',
1044
                        $anomes
1045
                    );
1046
                }
1047
                break;
1048
            }
1049
        }
1050
        return (string) $procXML;
1051
    }
1052
1053
    public static function validarXmlCte($xml, $schema)
1054
    {
1055
        $aResp = array();
1056
        $schem = IdentifyCTe::identificar($xml, $aResp);
1057
        if ($schem == '') {
1058
            return ["Não foi possível identificar o documento"];
1059
        }
1060
        $xsdFile = "{$aResp['Id']}_v{$aResp['versao']}.xsd";
1061
        $xsdPath = implode(DIRECTORY_SEPARATOR, [dirname(__DIR__), 'schemas', $schema, $xsdFile]);
1062
        if (!is_file($xsdPath)) {
1063
            return ["O arquivo XSD {$xsdFile} não foi localizado."];
1064
        }
1065
        if (!ValidXsd::validar($aResp['xml'], $xsdPath)) {
1066
            return ValidXsd::$errors;
1067
        }
1068
        return [];
1069
    }
1070
1071
    public static function serializarMensagemDoEventoCartaDeCorrecao(array $infCorrecoes)
1072
    {
1073
        // Grupo de Informações de Correção
1074
        $correcoes = '';
1075
        foreach ($infCorrecoes as $info) {
1076
            $nroItemAlteradoOptionalElement = '';
1077
            if (key_exists('nroItemAlterado', $info)) {
1078
                $nroItemAlteradoOptionalElement = "<nroItemAlterado>{$info['nroItemAlterado']}</nroItemAlterado>";
1079
            }
1080
            $correcoes .= "<infCorrecao>" .
1081
                "<grupoAlterado>{$info['grupoAlterado']}</grupoAlterado>" .
1082
                "<campoAlterado>{$info['campoAlterado']}</campoAlterado>" .
1083
                "<valorAlterado>{$info['valorAlterado']}</valorAlterado>" .
1084
                "{$nroItemAlteradoOptionalElement}" .
1085
                "</infCorrecao>";
1086
        }
1087
        //monta mensagem
1088
        return "<evCCeCTe>" .
1089
            "<descEvento>Carta de Correcao</descEvento>" .
1090
            "{$correcoes}" .
1091
            "<xCondUso>" .
1092
            "A Carta de Correcao e disciplinada pelo Art. 58-B do " .
1093
            "CONVENIO/SINIEF 06/89: Fica permitida a utilizacao de carta de " .
1094
            "correcao, para regularizacao de erro ocorrido na emissao de " .
1095
            "documentos fiscais relativos a prestacao de servico de transporte, " .
1096
            "desde que o erro nao esteja relacionado com: I - as variaveis que " .
1097
            "determinam o valor do imposto tais como: base de calculo, " .
1098
            "aliquota, diferenca de preco, quantidade, valor da prestacao;II - " .
1099
            "a correcao de dados cadastrais que implique mudanca do emitente, " .
1100
            "tomador, remetente ou do destinatario;III - a data de emissao ou " .
1101
            "de saida." .
1102
            "</xCondUso>" .
1103
        "</evCCeCTe>";
1104
    }
1105
}
1106