Total Complexity | 47 |
Total Lines | 507 |
Duplicated Lines | 0 % |
Changes | 6 | ||
Bugs | 0 | Features | 0 |
Complex classes like Cliente 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.
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 Cliente, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
10 | class Cliente |
||
11 | { |
||
12 | /** |
||
13 | * @var string $usuario Usuário de autenticação. |
||
14 | */ |
||
15 | private $usuario; |
||
16 | |||
17 | /** |
||
18 | * @var string $senha Senha de autenticação. |
||
19 | */ |
||
20 | private $senha; |
||
21 | |||
22 | /** |
||
23 | * @var string $numeroCartaoPostagem Número do cartão de postagem. |
||
24 | */ |
||
25 | private $numeroCartaoPostagem; |
||
26 | |||
27 | /** |
||
28 | * @var string $token Token de autenticação. |
||
29 | */ |
||
30 | private $token; |
||
31 | |||
32 | /** |
||
33 | * @var int $tokenExpiration Timestamp de expiração do token. |
||
34 | */ |
||
35 | private $tokenExpiration; |
||
36 | |||
37 | /** |
||
38 | * @var string $baseUrl URL base da API dos Correios. |
||
39 | */ |
||
40 | private $baseUrl; |
||
41 | |||
42 | /** |
||
43 | * @var array $produtos Lista de produtos a serem consultados. |
||
44 | */ |
||
45 | private $produtos = []; |
||
46 | |||
47 | /** |
||
48 | * @var array $respostaPreco Resposta da consulta de preços. |
||
49 | */ |
||
50 | private $respostaPreco; |
||
51 | |||
52 | /** |
||
53 | * @var array $respostaPrazo Resposta da consulta de prazos. |
||
54 | */ |
||
55 | private $respostaPrazo; |
||
56 | |||
57 | /** |
||
58 | * Construtor da classe Cliente. |
||
59 | * |
||
60 | * @param string $usuario Usuário de autenticação. |
||
61 | * @param string $senha Senha de autenticação. |
||
62 | * @param string $numeroCartaoPostagem Número do cartão de postagem. |
||
63 | * @param bool $producao Indica se é ambiente de produção (true) ou homologação (false). |
||
64 | */ |
||
65 | public function __construct($usuario, $senha, $numeroCartaoPostagem, $producao = true) |
||
66 | { |
||
67 | $this->usuario = $usuario; |
||
68 | $this->senha = $senha; |
||
69 | $this->numeroCartaoPostagem = $numeroCartaoPostagem; |
||
70 | $this->baseUrl = $producao ? "https://api.correios.com.br" : "https://apihom.correios.com.br"; |
||
71 | $this->token = $this->obterToken(); |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Obtém o token de autenticação. |
||
76 | * |
||
77 | * @return string Token de autenticação. |
||
78 | * @throws ClienteException Em caso de erro na obtenção do token. |
||
79 | */ |
||
80 | private function obterToken() |
||
81 | { |
||
82 | $credenciais = base64_encode("{$this->usuario}:{$this->senha}"); |
||
83 | $ch = curl_init(); |
||
84 | curl_setopt($ch, CURLOPT_URL, "{$this->baseUrl}/token/v1/autentica/cartaopostagem"); |
||
85 | curl_setopt($ch, CURLOPT_POST, 1); |
||
86 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["numero" => $this->numeroCartaoPostagem])); |
||
87 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ |
||
88 | "Content-Type: application/json", |
||
89 | "Authorization: Basic $credenciais" |
||
90 | ]); |
||
91 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||
92 | $response = curl_exec($ch); |
||
93 | |||
94 | if (curl_errno($ch)) { |
||
95 | throw new ClienteException('Erro ao obter token: ' . curl_error($ch)); |
||
96 | } |
||
97 | |||
98 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||
99 | curl_close($ch); |
||
100 | |||
101 | if ($httpCode != 201) { |
||
102 | throw new ClienteException('Erro ao obter token', $httpCode, $response); |
||
103 | } |
||
104 | |||
105 | if (is_string($response)) { |
||
106 | $responseDecoded = json_decode($response, true); |
||
107 | $this->tokenExpiration = time() + 3600; // Supondo que o token expira em 1 hora |
||
108 | } else { |
||
109 | throw new ClienteException('Erro ao obter token: resposta inválida recebida.'); |
||
110 | } |
||
111 | |||
112 | return $responseDecoded['token']; |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * Verifica a validade do token e renova se necessário. |
||
117 | */ |
||
118 | private function verificarToken() |
||
119 | { |
||
120 | if (time() >= $this->tokenExpiration) { |
||
121 | $this->token = $this->obterToken(); |
||
122 | } |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Insere um produto na lista de produtos a serem consultados. |
||
127 | * |
||
128 | * @param string $coProduto Código do produto. |
||
129 | * @param array $arrProduto Dados do produto. |
||
130 | */ |
||
131 | public function inserirProduto($coProduto, array $arrProduto) |
||
132 | { |
||
133 | $arrProduto['coProduto'] = $coProduto; |
||
134 | $this->produtos[] = $arrProduto; |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * Consulta o preço dos produtos inseridos dividindo-os em lotes. |
||
139 | * |
||
140 | * @return array A resposta da consulta de preço. |
||
141 | * @throws ClienteException Se ocorrer um erro durante a consulta. |
||
142 | */ |
||
143 | public function consultarPreco() |
||
144 | { |
||
145 | if (empty($this->produtos)) { |
||
146 | throw new ClienteException('Nenhum produto inserido para consulta de preço.'); |
||
147 | } |
||
148 | |||
149 | $this->verificarToken(); |
||
150 | $chunks = $this->criarChunksDeProdutosPreco($this->produtos); |
||
151 | $this->respostaPreco = $this->consultarPrecoEmChunks($chunks); |
||
152 | return $this->respostaPreco; |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * Cria lotes de produtos divididos em grupos de no máximo 5 itens. |
||
157 | * |
||
158 | * @param array $produtos Os produtos a serem divididos em lotes. |
||
159 | * @return array Os produtos divididos em lotes de no máximo 5 itens. |
||
160 | */ |
||
161 | private function criarChunksDeProdutosPreco(array $produtos) |
||
162 | { |
||
163 | return array_chunk($produtos, 5); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Consulta o preço dos produtos em lotes e retorna as respostas. |
||
168 | * |
||
169 | * @param array $chunks Os lotes de produtos a serem consultados. |
||
170 | * @return array As respostas da consulta de preço. |
||
171 | * @throws ClienteException Se ocorrer um erro durante a consulta. |
||
172 | */ |
||
173 | private function consultarPrecoEmChunks(array $chunks) |
||
174 | { |
||
175 | $responses = []; |
||
176 | |||
177 | foreach ($chunks as $chunk) { |
||
178 | $ch = curl_init(); |
||
179 | curl_setopt($ch, CURLOPT_URL, "{$this->baseUrl}/preco/v1/nacional"); |
||
180 | curl_setopt($ch, CURLOPT_POST, 1); |
||
181 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ |
||
182 | "idLote" => "1", |
||
183 | "parametrosProduto" => $chunk |
||
184 | ])); |
||
185 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ |
||
186 | "Content-Type: application/json", |
||
187 | "Authorization: Bearer {$this->token}" |
||
188 | ]); |
||
189 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||
190 | $response = curl_exec($ch); |
||
191 | |||
192 | if (curl_errno($ch)) { |
||
193 | throw new ClienteException('Erro ao consultar preço: ' . curl_error($ch)); |
||
194 | } |
||
195 | |||
196 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||
197 | curl_close($ch); |
||
198 | |||
199 | if ($httpCode != 200) { |
||
200 | throw new ClienteException('Erro ao consultar preço', $httpCode, $response); |
||
201 | } |
||
202 | |||
203 | if (is_string($response)) { |
||
204 | $responses[] = json_decode($response, true); |
||
205 | } else { |
||
206 | throw new ClienteException('Erro ao consultar preço: resposta inválida recebida.'); |
||
207 | } |
||
208 | } |
||
209 | |||
210 | return array_merge(...$responses); |
||
211 | } |
||
212 | |||
213 | /** |
||
214 | * Consulta o preço total de um produto específico. |
||
215 | * |
||
216 | * @param string $coProduto Código do produto. |
||
217 | * @return float Preço total do produto. |
||
218 | * @throws ClienteException Em caso de erro na consulta de preços ou se preços não foram consultados ainda. |
||
219 | */ |
||
220 | public function consultarPrecoTotal($coProduto) |
||
221 | { |
||
222 | if (empty($this->respostaPreco)) { |
||
223 | throw new ClienteException('Preço não foi consultado ainda.'); |
||
224 | } |
||
225 | |||
226 | $total = 0; |
||
227 | foreach ($this->respostaPreco as $produto) { |
||
228 | if ($produto['coProduto'] === $coProduto) { |
||
229 | $total += (float)str_replace(',', '.', $produto['pcFinal']); |
||
230 | } |
||
231 | } |
||
232 | |||
233 | return $total; |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * Consulta os prazos de entrega dos produtos inseridos. |
||
238 | * |
||
239 | * @param string $dataPostagem Data de postagem no formato YYYY-MM-DD. |
||
240 | * @param string $cepOrigem CEP de origem. |
||
241 | * @param string $cepDestino CEP de destino. |
||
242 | * @param string|null $dtEvento Data do evento no formato DD-MM-YYYY (opcional). |
||
243 | * @return array Resposta da consulta de prazos. |
||
244 | * @throws ClienteException Em caso de erro na consulta de prazos. |
||
245 | */ |
||
246 | public function consultarPrazo($dataPostagem, $cepOrigem, $cepDestino, $dtEvento = null) |
||
247 | { |
||
248 | if (empty($this->produtos)) { |
||
249 | throw new ClienteException('Nenhum produto inserido para consulta de prazo.'); |
||
250 | } |
||
251 | |||
252 | $this->verificarToken(); // Verifica se o token de autenticação é válido e, se necessário, renova o token. |
||
253 | $dtEvento = $dtEvento ? $dtEvento : date("d-m-Y", strtotime($dataPostagem)); // Define a data do evento. Se $dtEvento não for fornecido, usa a data de postagem convertida para o formato DD-MM-YYYY. |
||
254 | |||
255 | $chunks = $this->criarChunksDeProdutosPrazo($dataPostagem, $cepOrigem, $cepDestino, $dtEvento); |
||
256 | |||
257 | $responses = $this->consultarPrazoEmChunks($chunks); |
||
258 | |||
259 | $this->respostaPrazo = array_merge(...$responses); |
||
260 | return $this->respostaPrazo; |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * Cria lotes de produtos divididos em grupos de no máximo 5 itens. |
||
265 | * |
||
266 | * @param string $dataPostagem A data de postagem no formato YYYY-MM-DD. |
||
267 | * @param string $cepOrigem O CEP de origem do envio. |
||
268 | * @param string $cepDestino O CEP de destino do envio. |
||
269 | * @param string $dtEvento A data do evento no formato DD-MM-YYYY. |
||
270 | * @return array Os produtos divididos em lotes de no máximo 5 itens. |
||
271 | */ |
||
272 | private function criarChunksDeProdutosPrazo($dataPostagem, $cepOrigem, $cepDestino, $dtEvento) |
||
273 | { |
||
274 | return array_chunk(array_map(function ($produto) use ($dataPostagem, $cepOrigem, $cepDestino, $dtEvento) { |
||
275 | return [ |
||
276 | "coProduto" => $produto['coProduto'], |
||
277 | "nuRequisicao" => $produto['nuRequisicao'], |
||
278 | "dtEvento" => $dtEvento, |
||
279 | "cepOrigem" => $cepOrigem, |
||
280 | "cepDestino" => $cepDestino, |
||
281 | "dataPostagem" => $dataPostagem |
||
282 | ]; |
||
283 | }, $this->produtos), 5); |
||
284 | } |
||
285 | |||
286 | /** |
||
287 | * Consulta o prazo de entrega dos produtos em lotes e retorna as respostas. |
||
288 | * |
||
289 | * @param array $chunks Os lotes de produtos a serem consultados. |
||
290 | * @return array As respostas da consulta de prazo de entrega. |
||
291 | * @throws ClienteException Se ocorrer um erro durante a consulta. |
||
292 | */ |
||
293 | private function consultarPrazoEmChunks($chunks) |
||
294 | { |
||
295 | $responses = []; |
||
296 | |||
297 | foreach ($chunks as $chunk) { |
||
298 | $ch = curl_init(); |
||
299 | curl_setopt($ch, CURLOPT_URL, "{$this->baseUrl}/prazo/v1/nacional"); |
||
300 | curl_setopt($ch, CURLOPT_POST, 1); |
||
301 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ |
||
302 | "idLote" => "1", |
||
303 | "parametrosPrazo" => $chunk |
||
304 | ])); |
||
305 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ |
||
306 | "Content-Type: application/json", |
||
307 | "Authorization: Bearer {$this->token}" |
||
308 | ]); |
||
309 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||
310 | $response = curl_exec($ch); |
||
311 | |||
312 | if (curl_errno($ch)) { |
||
313 | throw new ClienteException('Erro ao consultar prazo: ' . curl_error($ch)); |
||
314 | } |
||
315 | |||
316 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||
317 | curl_close($ch); |
||
318 | |||
319 | if ($httpCode != 200) { |
||
320 | throw new ClienteException('Erro ao consultar prazo', $httpCode, $response); |
||
321 | } |
||
322 | |||
323 | if (is_string($response)) { |
||
324 | $responses[] = json_decode($response, true); |
||
325 | } else { |
||
326 | throw new ClienteException('Erro ao consultar prazo: resposta inválida recebida.'); |
||
327 | } |
||
328 | } |
||
329 | |||
330 | return $responses; |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * Consulta o prazo total de entrega de um produto específico. |
||
335 | * |
||
336 | * @param string $coProduto Código do produto. |
||
337 | * @return array Prazo total de entrega do produto. |
||
338 | * @throws ClienteException Em caso de erro na consulta de prazos ou se prazos não foram consultados ainda. |
||
339 | */ |
||
340 | public function consultarPrazoTotal($coProduto) |
||
341 | { |
||
342 | if (empty($this->respostaPrazo)) { |
||
343 | throw new ClienteException('Prazo não foi consultado ainda.'); |
||
344 | } |
||
345 | |||
346 | foreach ($this->respostaPrazo as $produto) { |
||
347 | if ($produto['coProduto'] === $coProduto) { |
||
348 | return $produto; |
||
349 | } |
||
350 | } |
||
351 | |||
352 | throw new ClienteException('Produto não encontrado na resposta do prazo.'); |
||
353 | } |
||
354 | |||
355 | /** |
||
356 | * Realiza a pré-postagem a faturar de objetos registrados. |
||
357 | * |
||
358 | * @param array $dadosPrePostagem Dados da pré-postagem. |
||
359 | * @return array Resposta da API dos Correios. |
||
360 | * @throws ClienteException Em caso de erro na solicitação. |
||
361 | */ |
||
362 | public function realizarPrePostagem(array $dadosPrePostagem) |
||
363 | { |
||
364 | $this->verificarToken(); |
||
365 | |||
366 | $ch = curl_init(); |
||
367 | curl_setopt($ch, CURLOPT_URL, "{$this->baseUrl}/prepostagem/v1/prepostagens"); |
||
368 | curl_setopt($ch, CURLOPT_POST, 1); |
||
369 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($dadosPrePostagem)); |
||
370 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ |
||
371 | "Content-Type: application/json", |
||
372 | "Authorization: Bearer {$this->token}" |
||
373 | ]); |
||
374 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||
375 | $response = curl_exec($ch); |
||
376 | |||
377 | if (curl_errno($ch)) { |
||
378 | throw new ClienteException('Erro ao realizar pré-postagem: ' . curl_error($ch)); |
||
379 | } |
||
380 | |||
381 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||
382 | curl_close($ch); |
||
383 | |||
384 | if ($httpCode != 200) { |
||
385 | throw new ClienteException('Erro ao realizar pré-postagem', $httpCode, $response); |
||
386 | } |
||
387 | |||
388 | return json_decode($response, true); |
||
389 | } |
||
390 | |||
391 | /** |
||
392 | * Cancela uma pré-postagem pelo identificador. |
||
393 | * |
||
394 | * @param string $idPrePostagem Identificador da pré-postagem. |
||
395 | * @param string|null $idSolicitante ID Correios do solicitante do cancelamento (opcional). |
||
396 | * @return array Resposta da API dos Correios. |
||
397 | * @throws ClienteException Se ocorrer um erro na solicitação. |
||
398 | */ |
||
399 | public function cancelarPrePostagem(string $idPrePostagem, string $idSolicitante = null) |
||
433 | } |
||
434 | |||
435 | /** |
||
436 | * Realiza a pré-postagem de múltiplos objetos registrados em um único envio. |
||
437 | * |
||
438 | * @param array $listaObjetos Lista de objetos para pré-postagem. |
||
439 | * @return array Resposta da API dos Correios. |
||
440 | * @throws ClienteException Em caso de erro na solicitação. |
||
441 | */ |
||
442 | public function realizarPrePostagemEmLote(array $listaObjetos) |
||
443 | { |
||
444 | $this->verificarToken(); |
||
445 | |||
446 | $caminhoArquivo = sys_get_temp_dir() . "/prepostagem.json"; |
||
447 | |||
448 | // Salvar o JSON no arquivo |
||
449 | file_put_contents($caminhoArquivo, json_encode([$listaObjetos])); |
||
450 | |||
451 | // Criar um objeto CURLFile para o upload do arquivo |
||
452 | $arquivo = new CURLFile($caminhoArquivo, 'application/json', 'prepostagem.json'); |
||
453 | |||
454 | $ch = curl_init(); |
||
455 | curl_setopt($ch, CURLOPT_URL, "{$this->baseUrl}/prepostagem/v1/prepostagens/lista/objetosregistrados"); |
||
456 | curl_setopt($ch, CURLOPT_POST, 1); |
||
457 | // curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($listaObjetos)); |
||
458 | curl_setopt($ch, CURLOPT_POSTFIELDS, ["arquivo" => $arquivo]); |
||
459 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ |
||
460 | "Content-Type: multipart/form-data", |
||
461 | "Authorization: Bearer {$this->token}" |
||
462 | ]); |
||
463 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||
464 | $response = curl_exec($ch); |
||
465 | |||
466 | if (curl_errno($ch)) { |
||
467 | throw new ClienteException('Erro ao realizar pré-postagem em lote: ' . curl_error($ch)); |
||
468 | } |
||
469 | |||
470 | $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||
471 | curl_close($ch); |
||
472 | |||
473 | if ($httpCode != 200) { |
||
474 | throw new ClienteException('Erro ao realizar pré-postagem em lote', $httpCode, $response); |
||
475 | } |
||
476 | |||
477 | return json_decode($response, true); |
||
478 | } |
||
479 | |||
480 | |||
481 | /** |
||
482 | * Gera o rótulo para o objeto previamente cadastrado na pré-postagem. |
||
483 | * |
||
484 | * @param string $idCorreios ID retornado na pré-postagem. |
||
485 | * @return string URL para download do rótulo. |
||
486 | * @throws ClienteException Em caso de erro na solicitação. |
||
487 | */ |
||
488 | public function gerarRotulo($idCorreios) |
||
517 | } |
||
518 | } |
||
519 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths