1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace NFePHP\Atende; |
4
|
|
|
|
5
|
|
|
use Exception; |
6
|
|
|
use RuntimeException; |
7
|
|
|
|
8
|
|
|
class Atende |
9
|
|
|
{ |
10
|
|
|
/** |
11
|
|
|
* @var string |
12
|
|
|
*/ |
13
|
|
|
protected $user; |
14
|
|
|
/** |
15
|
|
|
* @var string |
16
|
|
|
*/ |
17
|
|
|
protected $password; |
18
|
|
|
/** |
19
|
|
|
* @var int |
20
|
|
|
*/ |
21
|
|
|
protected $tpAmb = 2; |
22
|
|
|
/** |
23
|
|
|
* @var string |
24
|
|
|
*/ |
25
|
|
|
protected $soaperror; |
26
|
|
|
/** |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
protected $soapinfo; |
30
|
|
|
/** |
31
|
|
|
* @var string |
32
|
|
|
*/ |
33
|
|
|
public $url = [ |
34
|
|
|
1 => "https://{city}.atende.net/atende.php?pg=services" |
35
|
|
|
. "&service=WFPAtuarialPadraoIPM&cidade=padrao", |
36
|
|
|
2 => "https://qualidadeatendenet56.ipm.com.br/rh04/atende.php" |
37
|
|
|
. "?pg=services&service=WFPAtuarialPadraoIPM&cidade={city}" |
38
|
|
|
]; |
39
|
|
|
/** |
40
|
|
|
* @var string |
41
|
|
|
*/ |
42
|
|
|
public $cidade = 'paranagua'; |
43
|
|
|
/** |
44
|
|
|
* @var int |
45
|
|
|
*/ |
46
|
|
|
public $codcidade = 3037; |
47
|
|
|
/** |
48
|
|
|
* @var int |
49
|
|
|
*/ |
50
|
|
|
public $soaptimeout = 10; |
51
|
|
|
/** |
52
|
|
|
* @var bool |
53
|
|
|
*/ |
54
|
|
|
public $debugmode = false; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Constructor |
58
|
|
|
* @param string $user |
59
|
|
|
* @param string $password |
60
|
|
|
* @param string $cidade |
61
|
|
|
* @param int $codcidade |
62
|
|
|
*/ |
63
|
|
|
public function __construct($user, $password, $cidade, $codcidade) |
64
|
|
|
{ |
65
|
|
|
$this->user = trim($user); |
66
|
|
|
$this->password = trim($password); |
67
|
|
|
$this->cidade = strtolower(trim($cidade)); |
68
|
|
|
$this->codcidade = $codcidade; |
69
|
|
|
if (empty($this->user) || empty($this->password)) { |
70
|
|
|
throw new RuntimeException("A identificação do usuário e a " |
71
|
|
|
. "senha são obrigatórios."); |
72
|
|
|
} |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Set environment 2 to tests and 1 to production |
77
|
|
|
* @param int $tpAmb |
78
|
|
|
* @return int |
79
|
|
|
*/ |
80
|
|
|
public function setAmbiente($tpAmb = null) |
81
|
|
|
{ |
82
|
|
|
if (!empty($tpAmb) && ($tpAmb == 1 || $tpAmb == 2)) { |
83
|
|
|
$this->tpAmb = $tpAmb; |
84
|
|
|
} |
85
|
|
|
return $this->tpAmb; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Set debugmod |
90
|
|
|
* When debugmod = true, files with soap content will be saved for analises |
91
|
|
|
* @param bool $flag |
92
|
|
|
* @return void |
93
|
|
|
*/ |
94
|
|
|
public function setDebugMode($flag = true) |
95
|
|
|
{ |
96
|
|
|
if (!empty($flag)) { |
97
|
|
|
$this->debugmode = $flag; |
98
|
|
|
} |
99
|
|
|
return $this->debugmode; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Set soap timeout parameter in seconds |
104
|
|
|
* @param int $sec |
105
|
|
|
* @return void |
106
|
|
|
*/ |
107
|
|
|
public function setSoapTimeOut($sec = 10) |
108
|
|
|
{ |
109
|
|
|
if (!empty($sec)) { |
110
|
|
|
$this->soaptimeout = $sec; |
111
|
|
|
} |
112
|
|
|
return $this->soaptimeout; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* Consulta Dados dos Afastamentos do Funcionário (getAfastamento) |
117
|
|
|
* Retorna os dados dos afastamentos de um ou mais funcionários |
118
|
|
|
* cadastrados no módulo da Folha de Pagamento do sistema Atende.Net. |
119
|
|
|
* |
120
|
|
|
* @param int $anomes (OBRIGATÓRIO) ex. 201612 |
121
|
|
|
* @param int $pagina |
122
|
|
|
* @param string $cpf |
123
|
|
|
* @param string $numeroMatricula |
124
|
|
|
* @param string $tipo |
125
|
|
|
* @param int $codigoRegime |
126
|
|
|
*/ |
127
|
|
View Code Duplication |
public function getAfastamento( |
|
|
|
|
128
|
|
|
$anomes, |
129
|
|
|
$pagina = null, |
130
|
|
|
$cpf = null, |
131
|
|
|
$numeroMatricula = null, |
132
|
|
|
$tipo = null, |
133
|
|
|
$codigoRegime = null |
134
|
|
|
) { |
135
|
|
|
$action = "getAfastamento"; |
136
|
|
|
$message = $this->build( |
137
|
|
|
$action, |
138
|
|
|
$anomes, |
139
|
|
|
$pagina, |
140
|
|
|
$cpf, |
141
|
|
|
$numeroMatricula, |
142
|
|
|
$tipo, |
143
|
|
|
$codigoRegime |
144
|
|
|
); |
145
|
|
|
$response = $this->send($action, $message); |
146
|
|
|
return $response; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Consulta Dados das Bases de Contribuição (getContribuicao) |
151
|
|
|
* Retorna os dados das bases de pagamento de um ou mais funcionários |
152
|
|
|
* cadastrados no módulo da Folha de Pagamento do sistema Atende.Net |
153
|
|
|
* |
154
|
|
|
* @param int $anomes (OBRIGATÓRIO) ex. 201612 |
155
|
|
|
* @param int $pagina |
156
|
|
|
* @param string $cpf |
157
|
|
|
* @param string $numeroMatricula |
158
|
|
|
* @param string $tipo |
159
|
|
|
* @param int $codigoRegime |
160
|
|
|
*/ |
161
|
|
View Code Duplication |
public function getContribuicao( |
|
|
|
|
162
|
|
|
$anomes, |
163
|
|
|
$pagina = null, |
164
|
|
|
$cpf = null, |
165
|
|
|
$numeroMatricula = null, |
166
|
|
|
$tipo = null, |
167
|
|
|
$codigoRegime = null |
168
|
|
|
) { |
169
|
|
|
$action = "getContribuicao"; |
170
|
|
|
$message = $this->build( |
171
|
|
|
$action, |
172
|
|
|
$anomes, |
173
|
|
|
$pagina, |
174
|
|
|
$cpf, |
175
|
|
|
$numeroMatricula, |
176
|
|
|
$tipo, |
177
|
|
|
$codigoRegime |
178
|
|
|
); |
179
|
|
|
$response = $this->send($action, $message); |
180
|
|
|
return $response; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Consulta Dados Pagamentos (getContribuicaoAnalitica) |
185
|
|
|
* Retorna os dados das folhas de pagamento de um ou mais funcionários |
186
|
|
|
* cadastrados no módulo da Folha de Pagamento do sistema Atende.Net |
187
|
|
|
* especificando verbas, referências e valores. |
188
|
|
|
* |
189
|
|
|
* @param int $anomes (OBRIGATÓRIO) ex. 201612 |
190
|
|
|
* @param int $pagina |
191
|
|
|
* @param string $cpf |
192
|
|
|
* @param string $numeroMatricula |
193
|
|
|
* @param string $tipo |
194
|
|
|
* @param int $codigoRegime |
195
|
|
|
*/ |
196
|
|
View Code Duplication |
public function getContribuicaoAnalitica( |
|
|
|
|
197
|
|
|
$anomes, |
198
|
|
|
$pagina = null, |
199
|
|
|
$cpf = null, |
200
|
|
|
$numeroMatricula = null, |
201
|
|
|
$tipo = null, |
202
|
|
|
$codigoRegime = null |
203
|
|
|
) { |
204
|
|
|
$action = "getContribuicaoAnalitica"; |
205
|
|
|
$message = $this->build( |
206
|
|
|
$action, |
207
|
|
|
$anomes, |
208
|
|
|
$pagina, |
209
|
|
|
$cpf, |
210
|
|
|
$numeroMatricula, |
211
|
|
|
$tipo, |
212
|
|
|
$codigoRegime |
213
|
|
|
); |
214
|
|
|
$response = $this->send($action, $message); |
215
|
|
|
return $response; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Dados dos Dependentes do Funcionário (getDependentes) |
220
|
|
|
* Retorna os dados dos dependentes dos funcionários e do relacionamento |
221
|
|
|
* de dependência no sistema Atende.Net. |
222
|
|
|
* |
223
|
|
|
* @param int $anomes (OBRIGATÓRIO) ex. 201612 |
224
|
|
|
* @param int $pagina |
225
|
|
|
* @param string $cpf |
226
|
|
|
* @param string $numeroMatricula |
227
|
|
|
* @param string $tipo |
228
|
|
|
* @param int $codigoRegime |
229
|
|
|
*/ |
230
|
|
View Code Duplication |
public function getDependentes( |
|
|
|
|
231
|
|
|
$anomes, |
232
|
|
|
$pagina = null, |
233
|
|
|
$cpf = null, |
234
|
|
|
$numeroMatricula = null, |
235
|
|
|
$tipo = null, |
236
|
|
|
$codigoRegime = null |
237
|
|
|
) { |
238
|
|
|
$action = "getDependentes"; |
239
|
|
|
$message = $this->build( |
240
|
|
|
$action, |
241
|
|
|
$anomes, |
242
|
|
|
$pagina, |
243
|
|
|
$cpf, |
244
|
|
|
$numeroMatricula, |
245
|
|
|
$tipo, |
246
|
|
|
$codigoRegime |
247
|
|
|
); |
248
|
|
|
$response = $this->send($action, $message); |
249
|
|
|
return $response; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* Consulta Dados de Funcionário (getServidor) |
254
|
|
|
* Retorna os dados cadastrais de um ou mais funcionários do módulo |
255
|
|
|
* da Folha de Pagamento do sistema Atende.Net. Se o funcionário for |
256
|
|
|
* aposentado ou pensionista trará informações do tipo de aposentadoria ou |
257
|
|
|
* tipo de pensão. Caso o funcionário pensionista seja responsável ou |
258
|
|
|
* dependente de um funcionário falecido no relacionamento |
259
|
|
|
* Funcionário x Pensão do tipo "Por Morte" trará também os dados do |
260
|
|
|
* funcionário falecido. |
261
|
|
|
* |
262
|
|
|
* @param int $anomes (OBRIGATÓRIO) ex. 201612 |
263
|
|
|
* @param int $pagina |
264
|
|
|
* @param string $cpf |
265
|
|
|
* @param string $numeroMatricula |
266
|
|
|
* @param string $tipo |
267
|
|
|
* @param int $codigoRegime |
268
|
|
|
*/ |
269
|
|
View Code Duplication |
public function getServidor( |
|
|
|
|
270
|
|
|
$anomes, |
271
|
|
|
$pagina = null, |
272
|
|
|
$cpf = null, |
273
|
|
|
$numeroMatricula = null, |
274
|
|
|
$tipo = null, |
275
|
|
|
$codigoRegime = null |
276
|
|
|
) { |
277
|
|
|
$action = "getServidor"; |
278
|
|
|
$message = $this->build( |
279
|
|
|
$action, |
280
|
|
|
$anomes, |
281
|
|
|
$pagina, |
282
|
|
|
$cpf, |
283
|
|
|
$numeroMatricula, |
284
|
|
|
$tipo, |
285
|
|
|
$codigoRegime |
286
|
|
|
); |
287
|
|
|
$response = $this->send($action, $message); |
288
|
|
|
return $response; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
/** |
292
|
|
|
* Consulta Dados Tempo de Contribuição do Funcionário |
293
|
|
|
* (getTempoContribuicao) |
294
|
|
|
* Retorna os dados dos tempos de contribuição anteriores dos funcionários |
295
|
|
|
* cadastrados no sistema Atende.Net |
296
|
|
|
* |
297
|
|
|
* @param int $anomes (OBRIGATÓRIO) ex. 201612 |
298
|
|
|
* @param int $pagina |
299
|
|
|
* @param string $cpf |
300
|
|
|
* @param string $numeroMatricula |
301
|
|
|
* @param string $tipo |
302
|
|
|
* @param int $codigoRegime |
303
|
|
|
*/ |
304
|
|
View Code Duplication |
public function getTempoContribuicao( |
|
|
|
|
305
|
|
|
$anomes, |
306
|
|
|
$pagina = null, |
307
|
|
|
$cpf = null, |
308
|
|
|
$numeroMatricula = null, |
309
|
|
|
$tipo = null, |
310
|
|
|
$codigoRegime = null |
311
|
|
|
) { |
312
|
|
|
$action = "getTempoContribuicao"; |
313
|
|
|
$message = $this->build( |
314
|
|
|
$action, |
315
|
|
|
$anomes, |
316
|
|
|
$pagina, |
317
|
|
|
$cpf, |
318
|
|
|
$numeroMatricula, |
319
|
|
|
$tipo, |
320
|
|
|
$codigoRegime |
321
|
|
|
); |
322
|
|
|
$response = $this->send($action, $message); |
323
|
|
|
return $response; |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Build message content |
328
|
|
|
* |
329
|
|
|
* @param string $action (OBRIGATÓRIO) |
330
|
|
|
* @param int $anomes (OBRIGATÓRIO) ex. 201612 |
331
|
|
|
* @param int $pagina |
332
|
|
|
* @param string $cpf |
333
|
|
|
* @param string $numeroMatricula |
334
|
|
|
* @param int $tipo |
335
|
|
|
* @param int $codigoRegime |
336
|
|
|
* @return string |
337
|
|
|
*/ |
338
|
|
|
protected function build( |
339
|
|
|
$action, |
340
|
|
|
$anomes, |
341
|
|
|
$pagina = null, |
342
|
|
|
$cpf = null, |
343
|
|
|
$numeroMatricula = null, |
344
|
|
|
$tipo = null, |
345
|
|
|
$codigoRegime = null |
346
|
|
|
) { |
347
|
|
|
$param = ""; |
348
|
|
|
$tagPagina = ""; |
349
|
|
|
if (!empty($pagina)) { |
350
|
|
|
$param = "Paginado"; |
351
|
|
|
$tagPagina = "<pagina xsi:type=\"xsd:int\">$pagina</pagina>"; |
352
|
|
|
} |
353
|
|
|
$message = "<net:$action " |
354
|
|
|
. "soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" |
355
|
|
|
. "<parametro xsi:type=\"net:ParametrosAvaliacaoAtuarial$param\">" |
356
|
|
|
. "<codigoCliente xsi:type=\"xsd:int\">$this->codcidade</codigoCliente>" |
357
|
|
|
. "<mesAno xsi:type=\"xsd:int\">$anomes</mesAno>"; |
358
|
|
|
$message .= $tagPagina; |
359
|
|
|
if (!empty($cpf)) { |
360
|
|
|
$message .= "<cpf xsi:type=\"xsd:string\">$cpf</cpf>"; |
361
|
|
|
} |
362
|
|
|
if (!empty($numeroMatricula)) { |
363
|
|
|
$message .= "<numeroMatricula " |
364
|
|
|
. "xsi:type=\"xsd:string\">$numeroMatricula</numeroMatricula>"; |
365
|
|
|
} |
366
|
|
|
if (!empty($tipo)) { |
367
|
|
|
$message .= "<tipo xsi:type=\"xsd:int\">$tipo</tipo>"; |
368
|
|
|
} |
369
|
|
|
if (!empty($codigoRegime)) { |
370
|
|
|
$message .= "<codigoRegime " |
371
|
|
|
. "xsi:type=\"xsd:int\">$codigoRegime</codigoRegime>"; |
372
|
|
|
} |
373
|
|
|
$message .= "</parametro></net:$action>"; |
374
|
|
|
return $message; |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
/** |
378
|
|
|
* Send SOAP message, and get response from webservice |
379
|
|
|
* @param string $action |
380
|
|
|
* @param string $message |
381
|
|
|
* @return string |
382
|
|
|
* @throws \RuntimeException |
383
|
|
|
*/ |
384
|
|
|
protected function send($action, $message) |
385
|
|
|
{ |
386
|
|
|
$envelope = "<soapenv:Envelope " |
387
|
|
|
. "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " |
388
|
|
|
. "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " |
389
|
|
|
. "xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " |
390
|
|
|
. "xmlns:net=\"net.atende\">" |
391
|
|
|
. "<soapenv:Header/>" |
392
|
|
|
. "<soapenv:Body>"; |
393
|
|
|
$envelope .= $message . "</soapenv:Body></soapenv:Envelope>"; |
394
|
|
|
|
395
|
|
|
$contentLength = strlen($envelope); |
396
|
|
|
$headers = [ |
397
|
|
|
'User-Agent: PHP-SOAP', |
398
|
|
|
'Accept-Encoding: gzip,deflate', |
399
|
|
|
'Content-Type: text/xml;charset=UTF-8', |
400
|
|
|
"SOAPAction: \"net.atende#$action\"", |
401
|
|
|
"Content-Length: $contentLength", |
402
|
|
|
'Expect: 100-continue', |
403
|
|
|
'Connection: Keep-Alive' |
404
|
|
|
]; |
405
|
|
|
|
406
|
|
|
$txtheaders = implode("\n", $headers); |
407
|
|
|
$url = $this->url[$this->tpAmb]; |
408
|
|
|
$url = str_replace("{city}", $this->cidade, $url); |
409
|
|
|
|
410
|
|
|
try { |
411
|
|
|
$oCurl = curl_init(); |
412
|
|
|
curl_setopt($oCurl, CURLOPT_URL, $url); |
413
|
|
|
curl_setopt($oCurl, CURLOPT_CONNECTTIMEOUT, $this->soaptimeout); |
414
|
|
|
curl_setopt($oCurl, CURLOPT_TIMEOUT, $this->soaptimeout + 20); |
415
|
|
|
//dont use security check |
416
|
|
|
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, 0); |
417
|
|
|
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, 0); |
418
|
|
|
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1); |
419
|
|
|
curl_setopt($oCurl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); |
420
|
|
|
curl_setopt($oCurl, CURLOPT_FAILONERROR, 0); |
421
|
|
|
curl_setopt($oCurl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); |
422
|
|
|
curl_setopt($oCurl, CURLOPT_USERPWD, $this->user.":".$this->password); |
423
|
|
|
curl_setopt($oCurl, CURLOPT_POST, 1); |
424
|
|
|
curl_setopt($oCurl, CURLOPT_POSTFIELDS, $envelope); |
425
|
|
|
curl_setopt($oCurl, CURLOPT_HEADER, 1); |
426
|
|
|
curl_setopt($oCurl, CURLOPT_HTTPHEADER, $headers); |
427
|
|
|
curl_setopt($oCurl, CURLOPT_VERBOSE, 1); |
428
|
|
|
curl_setopt($oCurl, CURLOPT_CERTINFO, 1); |
429
|
|
|
|
430
|
|
|
$response = curl_exec($oCurl); |
431
|
|
|
|
432
|
|
|
$this->soaperror = curl_error($oCurl); |
433
|
|
|
$this->soapinfo = curl_getinfo($oCurl); |
434
|
|
|
|
435
|
|
|
$headsize = curl_getinfo($oCurl, CURLINFO_HEADER_SIZE); |
436
|
|
|
$httpcode = curl_getinfo($oCurl, CURLINFO_HTTP_CODE); |
437
|
|
|
$bodysize = curl_getinfo($oCurl, CURLINFO_CONTENT_LENGTH_DOWNLOAD); |
|
|
|
|
438
|
|
|
$bodyType = curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE); |
|
|
|
|
439
|
|
|
|
440
|
|
|
curl_close($oCurl); |
441
|
|
|
|
442
|
|
|
$responseHead = substr($response, 0, $headsize); |
443
|
|
|
$responseBody = substr($response, $headsize); |
444
|
|
|
if (substr($response, -3) !== substr($responseBody, -3)) { |
445
|
|
|
throw new \RuntimeException( |
446
|
|
|
'A terminação dos dados compactados está diferente! Não foi possivel extrair os dados.' |
447
|
|
|
); |
448
|
|
|
} |
449
|
|
|
$marker = substr($responseBody, 0, 3); |
450
|
|
|
//identify compress body in gzip deflate |
451
|
|
|
if ($marker === chr(0x1F).chr(0x8B).chr(0x08)) { |
452
|
|
|
$responseBody = gzdecode($responseBody); |
453
|
|
|
} |
454
|
|
|
$this->saveDebugFiles( |
455
|
|
|
$action, |
456
|
|
|
$txtheaders . "\n" . $envelope, |
457
|
|
|
$responseHead . "\n" . $responseBody, |
458
|
|
|
$this->debugmode |
459
|
|
|
); |
460
|
|
|
} catch (\Exception $e) { |
461
|
|
|
throw new \RuntimeException($e->getMessage()); |
462
|
|
|
} |
463
|
|
|
if ($this->soaperror != '') { |
464
|
|
|
throw new \RuntimeException($this->soaperror); |
465
|
|
|
} |
466
|
|
|
if ($httpcode != 200) { |
467
|
|
|
throw new \RuntimeException($responseHead . '\n' . $responseBody); |
468
|
|
|
} |
469
|
|
|
return $responseBody; |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* Save request envelope and response for debug reasons |
474
|
|
|
* @param string $action |
475
|
|
|
* @param string $request |
476
|
|
|
* @param string $response |
477
|
|
|
* @return void |
478
|
|
|
*/ |
479
|
|
|
protected function saveDebugFiles($action, $request, $response, $flag = false) |
480
|
|
|
{ |
481
|
|
|
if (!$flag) { |
482
|
|
|
return; |
483
|
|
|
} |
484
|
|
|
$tempdir = sys_get_temp_dir() |
485
|
|
|
. DIRECTORY_SEPARATOR |
486
|
|
|
. 'soap' |
487
|
|
|
. DIRECTORY_SEPARATOR; |
488
|
|
|
if (! is_dir($tempdir)) { |
489
|
|
|
mkdir($tempdir, 0777); |
490
|
|
|
} |
491
|
|
|
$num = date('mdHis'); |
492
|
|
|
file_put_contents($tempdir . "req_" . $action . "_" . $num . ".txt", $request); |
493
|
|
|
file_put_contents($tempdir . "res_" . $action . "_" . $num . ".txt", $response); |
494
|
|
|
} |
495
|
|
|
} |
496
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.