Completed
Pull Request — master (#77)
by Roberto
03:19
created

Tools   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 648
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 50
lcom 1
cbo 6
dl 0
loc 648
ccs 0
cts 469
cp 0
rs 8.352
c 0
b 0
f 0

16 Methods

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