Completed
Push — master ( 8e61b1...771dc2 )
by Roberto
08:19 queued 10s
created

Tools   C

Complexity

Total Complexity 56

Size/Duplication

Total Lines 650
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 56
lcom 1
cbo 7
dl 0
loc 650
ccs 0
cts 470
cp 0
rs 5.47
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A consultR1() 0 11 1
A __construct() 0 4 1
A loadSoapClass() 0 4 1
C consultar() 0 65 15
A consultConsolidadas() 0 20 1
A consultR2010() 0 46 2
A consultR2020() 0 44 2
A consultR20() 0 36 3
A consultR2055() 0 37 3
A consultR2060() 0 43 2
A consultR209() 0 23 2
A consultR3010() 0 34 2
B enviarLoteEventos() 0 50 6
A sendRequest() 0 36 4
A checkCertificate() 0 8 2
B validInputParameters() 0 22 9

How to fix   Complexity   

Complex Class

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

1
<?php
2
3
namespace NFePHP\EFDReinf;
4
5
/**
6
 * Classe Tools, performs communication with the EFDReinf webservice
7
 *
8
 * @category  Library
9
 * @package   NFePHP\EFDReinf\Tools
10
 * @copyright Copyright (c) 2017-2021
11
 * @license   https://www.gnu.org/licenses/lgpl-3.0.txt LGPLv3
12
 * @license   https://www.gnu.org/licenses/gpl-3.0.txt GPLv3
13
 * @license   https://opensource.org/licenses/mit-license.php MIT
14
 * @author    Roberto L. Machado <linux.rlm at gmail dot com>
15
 * @link      http://github.com/nfephp-org/sped-efdreinf for the canonical source repository
16
 */
17
use NFePHP\Common\Certificate;
18
use NFePHP\Common\Validator;
19
use NFePHP\EFDReinf\Common\Tools as ToolsBase;
20
use NFePHP\EFDReinf\Common\FactoryInterface;
21
use NFePHP\EFDReinf\Common\Soap\SoapCurl;
22
use NFePHP\EFDReinf\Common\Soap\SoapInterface;
23
use NFePHP\EFDReinf\Exception\ProcessException;
24
use stdClass;
25
use NFePHP\EFDReinf\Common\Factory;
26
27
class Tools extends ToolsBase
28
{
29
    const CONSULTA_CONSOLIDADA = 1;
30
    const CONSULTA_R1000 = 2;
31
    const CONSULTA_R1070 = 3;
32
    const CONSULTA_R2010 = 4;
33
    const CONSULTA_R2020 = 5;
34
    const CONSULTA_R2030 = 6;
35
    const CONSULTA_R2040 = 7;
36
    const CONSULTA_R2050 = 8;
37
    const CONSULTA_R2055 = 13;
38
    const CONSULTA_R2060 = 9;
39
    const CONSULTA_R2098 = 10;
40
    const CONSULTA_R2099 = 11;
41
    const CONSULTA_R3010 = 12;
42
43
    /**
44
     * @var string
45
     */
46
    public $lastRequest;
47
    /**
48
     * @var string
49
     */
50
    public $lastResponse;
51
    /**
52
     * @var SoapInterface
53
     */
54
    public $soap;
55
    /**
56
     * @var string
57
     */
58
    public $namespace = 'http://sped.fazenda.gov.br/';
59
    /**
60
     * @var array
61
     */
62
    protected $soapnamespaces = [
63
        'xmlns:soapenv' => "http://schemas.xmlsoap.org/soap/envelope/",
64
        'xmlns:sped'=> "http://sped.fazenda.gov.br/"
65
    ];
66
    /**
67
     * @var array
68
     */
69
    protected $uri = [
70
        '1' => 'https://reinf.receita.fazenda.gov.br/WsREINF/RecepcaoLoteReinf.svc',
71
        '2' => 'https://preprodefdreinf.receita.fazenda.gov.br/WsREINF/RecepcaoLoteReinf.svc'
72
73
    ];
74
    /**
75
     * @var array
76
     */
77
    protected $uriconsulta = [
78
        '1' => 'https://reinf.receita.fazenda.gov.br/WsReinfConsultas/ConsultasReinf.svc',
79
        '2' => 'https://preprodefdreinf.receita.fazenda.gov.br/WsReinfConsultas/ConsultasReinf.svc'
80
    ];
81
82
    /**
83
     * @var string
84
     */
85
    protected $action;
86
    /**
87
     * @var string
88
     */
89
    protected $method;
90
91
    /**
92
     * Constructor
93
     * @param string $config
94
     * @param Certificate $certificate
95
     */
96
    public function __construct($config, Certificate $certificate)
97
    {
98
        parent::__construct($config, $certificate);
99
    }
100
101
    /**
102
     * SOAP communication dependency injection
103
     * @param SoapInterface $soap
104
     */
105
    public function loadSoapClass(SoapInterface $soap)
106
    {
107
        $this->soap = $soap;
108
    }
109
110
    /**
111
     * Run EFD-REINF Query
112
     * @param integer $mod
113
     * @param stdClass $std
114
     * @throws ProcessException
115
     */
116
    public function consultar($mod, stdClass $std = null)
117
    {
118
        if (isset($std)) {
119
            //converte os nomes das propriedades do stdClass para caixa baixa
120
            $std = Factory::propertiesToLower($std);
121
        }
122
        switch ($mod) {
123
            case 1:
124
                $evt = 0;
125
                $request = $this->consultConsolidadas($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultConsolidadas() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
126
                break;
127
            case 2:
128
                $evt = 1000;
129
                $request = $this->consultR1($evt);
130
                break;
131
            case 3:
132
                $evt = 1070;
133
                $request = $this->consultR1($evt);
134
                break;
135
            case 4:
136
                $evt = 2010;
137
                $request = $this->consultR2010($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR2010() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
138
                break;
139
            case 5:
140
                $evt = 2020;
141
                $request = $this->consultR2020($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR2020() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
142
                break;
143
            case 6:
144
                $evt = 2030;
145
                $request = $this->consultR20($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR20() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
146
                break;
147
            case 7:
148
                $evt = 2040;
149
                $request = $this->consultR20($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR20() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
150
                break;
151
            case 8:
152
                $evt = 2050;
153
                $request = $this->consultR20($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR20() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
154
                break;
155
            case 9:
156
                $evt = 2060;
157
                $request = $this->consultR2060($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR2060() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
158
                break;
159
            case 10:
160
                $evt = 2098;
161
                $request = $this->consultR209($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR209() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
162
                break;
163
            case 11:
164
                $evt = 2099;
165
                $request = $this->consultR209($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR209() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
166
                break;
167
            case 12:
168
                $evt = 3010;
169
                $request = $this->consultR3010($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR3010() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
170
                break;
171
            case 13:
172
                $evt = 2055;
173
                $request = $this->consultR2055($evt, $std);
0 ignored issues
show
Bug introduced by
It seems like $std defined by parameter $std on line 116 can be null; however, NFePHP\EFDReinf\Tools::consultR2055() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
174
                break;
175
            default:
176
                throw ProcessException::wrongArgument(2003, '');
177
        }
178
        $this->lastResponse = $this->sendRequest($request);
179
        return $this->lastResponse;
180
    }
181
182
    /**
183
     * Consultation of consolidated information
184
     * @param integer $evt
185
     * @param stdClass $std
186
     * @return string
187
     */
188
    public function consultConsolidadas($evt, stdClass $std)
0 ignored issues
show
Unused Code introduced by
The parameter $evt 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...
189
    {
190
        $properties = [
191
            'numeroprotocolofechamento' => [
192
                'required' => true,
193
                'type' => 'string',
194
                'regex' => ''
195
            ],
196
        ];
197
        $this->validInputParameters($properties, $std);
198
199
        $this->method = "ConsultaInformacoesConsolidadas";
200
        $this->action = "{$this->namespace}ConsultasReinf/{$this->method}";
201
        $request = "<sped:{$this->method}>"
202
            . "<sped:tipoInscricaoContribuinte>{$this->tpInsc}</sped:tipoInscricaoContribuinte>"
203
            . "<sped:numeroInscricaoContribuinte>{$this->nrInsc}</sped:numeroInscricaoContribuinte>"
204
            . "<sped:numeroProtocoloFechamento>{$std->numeroprotocolofechamento}</sped:numeroProtocoloFechamento>"
205
            . "</sped:{$this->method}>";
206
        return $request;
207
    }
208
    
209
210
    /**
211
     * Consultation R1000 and R1070
212
     * @param integer $evt
213
     * @return string
214
     */
215
    protected function consultR1($evt)
216
    {
217
        $this->method = "ConsultaReciboEvento{$evt}";
218
        $this->action = "{$this->namespace}ConsultasReinf/{$this->method}";
219
        $request = "<sped:{$this->method}>"
220
            . "<sped:tipoEvento>{$evt}</sped:tipoEvento>"
221
            . "<sped:tpInsc>{$this->tpInsc}</sped:tpInsc>"
222
            . "<sped:nrInsc>{$this->nrInsc}</sped:nrInsc>"
223
            . "</sped:{$this->method}>";
224
        return $request;
225
    }
226
227
    /**
228
     * Consultation R2010
229
     * @param integer $evt
230
     * @param stdClass $std
231
     * @return string
232
     */
233
    protected function consultR2010($evt, $std)
234
    {
235
        $properties = [
236
            'perapur' => [
237
                'required' => false,
238
                'type' => ['string',"null"],
239
                'regex' => '^(19[0-9][0-9]|2[0-9][0-9][0-9])[-](0?[1-9]|1[0-2])$'
240
            ],
241
            'tpinscestab' => [
242
                'required' => true,
243
                'type' => 'integer',
244
                'min' => 1,
245
                'max' => 2
246
            ],
247
            'nrinscestab' => [
248
                'required' => true,
249
                'type' => 'string',
250
                'regex' => '^[0-9]{11,14}$'
251
            ],
252
            'cnpjprestador' => [
253
                'required' => true,
254
                'type' => 'string',
255
                'regex' => '^[0-9]{14}$'
256
            ],
257
        ];
258
        $this->validInputParameters($properties, $std);
259
260
        $this->method = "ConsultaReciboEvento{$evt}";
261
        $this->action = "{$this->namespace}ConsultasReinf/{$this->method}";
262
        $request = "<sped:{$this->method}>"
263
            . "<sped:tipoEvento>{$evt}</sped:tipoEvento>"
264
            . "<sped:tpInsc>{$this->tpInsc}</sped:tpInsc>"
265
            . "<sped:nrInsc>{$this->nrInsc}</sped:nrInsc>";
266
        if (!empty($std->perapur)) {
267
            $request .=  "<sped:perApur>{$std->perapur}</sped:perApur>";
268
        }
269
        $request .= "<sped:tpInscEstab>{$std->tpinscestab}</sped:tpInscEstab>"
270
            . "<sped:nrInscEstab>"
271
                . str_pad($std->nrinscestab, 14, '0', STR_PAD_LEFT)
272
                . "</sped:nrInscEstab>"
273
            . "<sped:cnpjPrestador>"
274
                . str_pad($std->cnpjprestador, 14, '0', STR_PAD_LEFT)
275
                . "</sped:cnpjPrestador>"
276
            . "</sped:{$this->method}>";
277
        return $request;
278
    }
279
280
    /**
281
     * Consultation R2020
282
     * @param integer $evt
283
     * @param stdClass $std
284
     * @return string
285
     */
286
    protected function consultR2020($evt, $std)
287
    {
288
        $properties = [
289
            'perapur' => [
290
                'required' => false,
291
                'type' => ['string',"null"],
292
                'regex' => '^(19[0-9][0-9]|2[0-9][0-9][0-9])[-](0?[1-9]|1[0-2])$'
293
             ],
294
            'nrinscestabprest' => [
295
                'required' => true,
296
                'type' => 'string',
297
                'regex' => '^[0-9]{11,14}$'
298
            ],
299
            'tpinsctomador' => [
300
                'required' => true,
301
                'type' => 'integer',
302
                'min' => 1,
303
                'max' => 4
304
            ],
305
            'nrinsctomador' => [
306
                'required' => true,
307
                'type' => 'string',
308
                'regex' => '^[0-9]{11,14}$'
309
            ],
310
        ];
311
        $this->validInputParameters($properties, $std);
312
313
        $this->method = "ConsultaReciboEvento{$evt}";
314
        $this->action = "{$this->namespace}ConsultasReinf/{$this->method}";
315
        $request = "<sped:{$this->method}>"
316
            . "<sped:tipoEvento>{$evt}</sped:tipoEvento>"
317
            . "<sped:tpInsc>{$this->tpInsc}</sped:tpInsc>"
318
            . "<sped:nrInsc>{$this->nrInsc}</sped:nrInsc>";
319
        if (!empty($std->perapur)) {
320
            $request .= "<sped:perApur>{$std->perapur}</sped:perApur>";
321
        }
322
        $request .= "<sped:nrInscEstabPrest>{$std->nrinscestabprest}</sped:nrInscEstabPrest>"
323
            . "<sped:tpInscTomador>{$std->tpinsctomador}</sped:tpInscTomador>"
324
            . "<sped:nrInscTomador>"
325
                . str_pad($std->nrinsctomador, 14, '0', STR_PAD_LEFT)
326
                . "</sped:nrInscTomador>"
327
            . "</sped:{$this->method}>";
328
        return $request;
329
    }
330
331
    /**
332
     * Consultation R2030, R2040, R2050
333
     * @param integer $evt
334
     * @param stdClass $std
335
     * @return string
336
     */
337
    protected function consultR20($evt, $std)
338
    {
339
        $properties = [
340
            'perapur' => [
341
                'required' => false,
342
                'type' => ['string',"null"],
343
                'regex' => '^(19[0-9][0-9]|2[0-9][0-9][0-9])[-](0?[1-9]|1[0-2])$'
344
            ],
345
            'nrinscestab' => [
346
                'required' => true,
347
                'type' => 'string',
348
                'regex' => '^[0-9]{11,14}$'
349
            ],
350
        ];
351
        $this->validInputParameters($properties, $std);
352
        if ($this->tpInsc !== 1) {
353
            throw new \InvalidArgumentException(
354
                "Somente com CNPJ essa consulta pode ser realizada."
355
                . " Seu config indica um CPF."
356
            );
357
        }
358
        $this->method = "ConsultaReciboEvento{$evt}";
359
        $this->action = "{$this->namespace}ConsultasReinf/{$this->method}";
360
        $request = "<sped:{$this->method}>"
361
            . "<sped:tipoEvento>{$evt}</sped:tipoEvento>"
362
            . "<sped:tpInsc>{$this->tpInsc}</sped:tpInsc>"
363
            . "<sped:nrInsc>{$this->nrInsc}</sped:nrInsc>";
364
        if (!empty($std->perapur)) {
365
            $request .= "<sped:perApur>{$std->perapur}</sped:perApur>";
366
        }
367
        $request .= "<sped:nrInscEstab>"
368
                . str_pad($std->nrinscestab, 14, '0', STR_PAD_LEFT)
369
                . "</sped:nrInscEstab>"
370
            . "</sped:{$this->method}>";
371
        return $request;
372
    }
373
    
374
    /**
375
     * Consultation R2055
376
     * @param integer $evt
377
     * @param stdClass $std
378
     * @return string
379
     */
380
    protected function consultR2055($evt, $std)
381
    {
382
        $properties = [
383
            'perapur' => [
384
                'required' => false,
385
                'type' => ['string',"null"],
386
                'regex' => '^(19[0-9][0-9]|2[0-9][0-9][0-9])[-](0?[1-9]|1[0-2])$'
387
            ],
388
            'nrinscestab' => [
389
                'required' => true,
390
                'type' => 'string',
391
                'regex' => '^[0-9]{11,14}$'
392
            ],
393
        ];
394
        $this->validInputParameters($properties, $std);
395
        if ($this->tpInsc !== 1) {
396
            throw new \InvalidArgumentException(
397
                "Somente com CNPJ essa consulta pode ser realizada."
398
                . " Seu config indica um CPF."
399
            );
400
        }
401
        $this->method = "ConsultaReciboEvento{$evt}";
402
        $this->action = "{$this->namespace}ConsultasReinf/{$this->method}";
403
        $request = "<sped:{$this->method}>"
404
            . "<sped:tipoEvento>{$evt}</sped:tipoEvento>"
405
            . "<sped:tpInsc>{$this->tpInsc}</sped:tpInsc>"
406
            . "<sped:nrInsc>{$this->nrInsc}</sped:nrInsc>";
407
        if (!empty($std->perapur)) {
408
            $request .= "<sped:perApur>{$std->perapur}</sped:perApur>";
409
        }
410
        $request .= "<sped:tpInscAdq>{$std->tpInscAdq}</sped:tpInscAdq>"
411
            . "<sped:nrInscAdq>{$std->nrInscAdq}</sped:nrInscAdq>"
412
            . "<sped:tpInscProd>{$std->tpInscProd}</sped:tpInscProd>"
413
            . "<sped:nrInscProd>{$std->nrInscProd}</sped:nrInscProd>"
414
            . "</sped:{$this->method}>";
415
        return $request;
416
    }
417
418
419
    /**
420
     * Consultation R2060
421
     * @param integer $evt
422
     * @param stdClass $std
423
     * @return string
424
     */
425
    protected function consultR2060($evt, $std)
426
    {
427
        $properties = [
428
            'perapur' => [
429
                'required' => false,
430
                'type' => ['string',"null"],
431
                'regex' => '^(19[0-9][0-9]|2[0-9][0-9][0-9])[-](0?[1-9]|1[0-2])$'
432
            ],
433
            'nrinscestabprest' => [
434
                'required' => true,
435
                'type' => 'string',
436
                'regex' => '^[0-9]{11,14}$'
437
            ],
438
            'tpinscestab' => [
439
                'required' => true,
440
                'type' => 'integer',
441
                'min' => 1,
442
                'max' => 2
443
            ],
444
            'nrinscestab' => [
445
                'required' => true,
446
                'type' => 'string',
447
                'regex' => '^[0-9]{11,14}$'
448
            ],
449
        ];
450
        $this->validInputParameters($properties, $std);
451
452
        $this->method = "ConsultaReciboEvento{$evt}";
453
        $this->action = "{$this->namespace}ConsultasReinf/{$this->method}";
454
        $request = "<sped:{$this->method}>"
455
            . "<sped:tipoEvento>{$evt}</sped:tipoEvento>"
456
            . "<sped:tpInsc>{$this->tpInsc}</sped:tpInsc>"
457
            . "<sped:nrInsc>{$this->nrInsc}</sped:nrInsc>";
458
        if (!empty($std->perapur)) {
459
            $request .= "<sped:perApur>{$std->perapur}</sped:perApur>";
460
        }
461
        $request .= "<sped:tpInscEstab>{$std->tpinscestab}</sped:tpInscEstab>"
462
            . "<sped:nrInscEstab>"
463
                . str_pad($std->nrinscestab, 14, '0', STR_PAD_LEFT)
464
                . "</sped:nrInscEstab>"
465
            . "</sped:{$this->method}>";
466
        return $request;
467
    }
468
469
    /**
470
     * Consultation R2098 and R2099
471
     * @param integer $evt
472
     * @param stdClass $std
473
     * @return string
474
     */
475
    protected function consultR209($evt, $std)
476
    {
477
        $properties = [
478
            'perapur' => [
479
                'required' => false,
480
                'type' => ['string',"null"],
481
                'regex' => '^(19[0-9][0-9]|2[0-9][0-9][0-9])[-](0?[1-9]|1[0-2])$'
482
            ],
483
        ];
484
        $this->validInputParameters($properties, $std);
485
486
        $this->method = "ConsultaReciboEvento{$evt}";
487
        $this->action = "{$this->namespace}ConsultasReinf/{$this->method}";
488
        $request = "<sped:{$this->method}>"
489
            . "<sped:tipoEvento>{$evt}</sped:tipoEvento>"
490
            . "<sped:tpInsc>{$this->tpInsc}</sped:tpInsc>"
491
            . "<sped:nrInsc>{$this->nrInsc}</sped:nrInsc>";
492
        if (!empty($std->perapur)) {
493
            $request .= "<sped:perApur>{$std->perapur}</sped:perApur>";
494
        }
495
        $request .= "</sped:{$this->method}>";
496
        return $request;
497
    }
498
499
    /**
500
     * Consultation R3010
501
     * @param integer $evt
502
     * @param stdClass $std
503
     * @return string
504
     */
505
    protected function consultR3010($evt, $std)
506
    {
507
        $properties = [
508
            'dtapur' => [
509
                'required' => true,
510
                'type' => 'string',
511
                'regex' => '^(19[0-9][0-9]|2[0-9][0-9][0-9])[-](0?[1-9]|1[0-2])[-](0?[1-9]|[1-2][0-9]|3[0-1])$'
512
            ],
513
            'nrinscestabelecimento' => [
514
                'required' => true,
515
                'type' => 'string',
516
                'regex' => '^[0-9]{11,14}$'
517
            ],
518
        ];
519
        $this->validInputParameters($properties, $std);
520
        if ($this->tpInsc !== 1) {
521
            throw new \InvalidArgumentException(
522
                "Somente com CNPJ essa consulta pode ser realizada."
523
                . " Seu config indica um CPF."
524
            );
525
        }
526
        $this->method = "ConsultaReciboEvento{$evt}";
527
        $this->action = "{$this->namespace}ConsultasReinf/{$this->method}";
528
        $request = "<sped:{$this->method}>"
529
            . "<sped:tipoEvento>{$evt}</sped:tipoEvento>"
530
            . "<sped:tpInsc>{$this->tpInsc}</sped:tpInsc>"
531
            . "<sped:nrInsc>{$this->nrInsc}</sped:nrInsc>"
532
            . "<sped:dtApur>{$std->dtapur}</sped:dtApur>"
533
            . "<sped:nrInscEstabelecimento>"
534
                . str_pad($std->nrinscestabelecimento, 14, '0', STR_PAD_LEFT)
535
                . "</sped:nrInscEstabelecimento>"
536
            . "</sped:{$this->method}>";
537
        return $request;
538
    }
539
540
    /**
541
     * Send batch of events
542
     * @param  integer $grupo
543
     * @param array $eventos
544
     * @return string
545
     */
546
    public function enviarLoteEventos($grupo, $eventos = [])
547
    {
548
        if (empty($eventos)) {
549
            return '';
550
        }
551
        //check number of events
552
        $nEvt = count($eventos);
553
        if ($nEvt > 100) {
554
            throw ProcessException::wrongArgument(2000, $nEvt);
555
        }
556
        $this->method = "ReceberLoteEventos";
557
        $this->action = "{$this->namespace}RecepcaoLoteReinf/{$this->method}";
558
        $xml = "";
559
        foreach ($eventos as $evt) {
560
            if (!is_a($evt, '\NFePHP\EFDReinf\Common\FactoryInterface')) {
561
                throw ProcessException::wrongArgument(2002, '');
562
            }
563
            //verifica se o evento pertence ao grupo indicado
564
            if (! in_array($evt->alias(), $this->grupos[$grupo])) {
565
                throw new \RuntimeException(
566
                    'O evento ' . $evt->alias() . ' não pertence a este grupo [ '
567
                    . $this->eventGroup[$grupo] . ' ].'
568
                );
569
            }
570
            $this->checkCertificate($evt);
571
            $xml .= "<evento id=\"".$evt->getId()."\">";
572
            $xml .= $evt->toXML();
573
            $xml .= "</evento>";
574
        }
575
        //build request
576
        $request = "<Reinf xmlns=\"http://www.reinf.esocial.gov.br/schemas/envioLoteEventos/v"
577
            . $this->serviceVersion."\" >"
578
            . "<loteEventos>"
579
            . $xml
580
            . "</loteEventos>"
581
            . "</Reinf>";
582
        //validate requisition with XSD
583
        $xsd = $this->path
584
            . "schemes/comunicacao/v$this->serviceVersion/"
585
            . $this->serviceXsd['EnvioLoteEventos']['name'];
586
        Validator::isValid($request, $xsd);
587
        //build soap body
588
        $body = "<sped:ReceberLoteEventos>"
589
            . "<sped:loteEventos>"
590
            . $request
591
            . "</sped:loteEventos>"
592
            . "</sped:ReceberLoteEventos>";
593
        $this->lastResponse = $this->sendRequest($body);
594
        return $this->lastResponse;
595
    }
596
597
    /**
598
     * Send request to webservice
599
     * @param string $request
600
     * @return string
601
     */
602
    protected function sendRequest($request)
603
    {
604
        if (empty($this->soap)) {
605
            $this->soap = new SoapCurl($this->certificate);
606
        }
607
        $envelope = "<soapenv:Envelope ";
608
        foreach ($this->soapnamespaces as $key => $xmlns) {
609
            $envelope .= "$key = \"$xmlns\" ";
610
        }
611
        $envelope .= ">"
612
            . "<soapenv:Header/>"
613
            . "<soapenv:Body>"
614
            . $request
615
            . "</soapenv:Body>"
616
            . "</soapenv:Envelope>";
617
618
        $msgSize = strlen($envelope);
619
        $parameters = [
620
            "Content-Type: text/xml;charset=UTF-8",
621
            "SOAPAction: \"$this->action\"",
622
            "Content-length: $msgSize"
623
        ];
624
        if ($this->method == 'ReceberLoteEventos') {
625
            $url = $this->uri[$this->tpAmb];
626
        } else {
627
            $url = $this->uriconsulta[$this->tpAmb];
628
        }
629
        $this->lastRequest = $envelope;
630
        return (string) $this->soap->send(
631
            $this->method,
632
            $url,
633
            $this->action,
634
            $envelope,
635
            $parameters
636
        );
637
    }
638
639
    /**
640
     * Verify the availability of a digital certificate.
641
     * If available, place it where it is needed
642
     * @param FactoryInterface $evento
643
     * @throws RuntimeException
644
     */
645
    protected function checkCertificate(FactoryInterface $evento)
646
    {
647
        //try to get certificate from event
648
        $certificate = $evento->getCertificate();
649
        if (empty($certificate)) {
650
            $evento->setCertificate($this->certificate);
651
        }
652
    }
653
654
    protected function validInputParameters($properties, $std)
655
    {
656
        foreach ($properties as $key => $rules) {
657
            $r = json_decode(json_encode($rules));
658
            if ($r->required) {
659
                if (!isset($std->$key)) {
660
                    throw new \Exception("$key não foi passado como parâmetro e é obrigatório.");
661
                }
662
                $value = $std->$key;
663
                if ($r->type === 'integer') {
664
                    if ($value < $r->min || $value > $r->max) {
665
                        throw new \Exception("$key contêm um valor invalido [$value].");
666
                    }
667
                }
668
                if ($r->type === 'string') {
669
                    if (!preg_match("/{$r->regex}/", $value)) {
670
                        throw new \Exception("$key contêm um valor invalido [$value].");
671
                    }
672
                }
673
            }
674
        }
675
    }
676
}
677