Total Complexity | 48 |
Total Lines | 386 |
Duplicated Lines | 0 % |
Coverage | 91.45% |
Changes | 0 |
Complex classes like Client 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 Client, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
132 | class Client extends AbstractHttpClient implements LoggerAwareInterface |
||
133 | { |
||
134 | const DEPRECATION_HEADER = 'X-DEPRECATION-NOTICE'; |
||
135 | |||
136 | /** |
||
137 | * @sideeffect Test123 |
||
138 | * @var LoggerInterface |
||
139 | */ |
||
140 | protected $logger; |
||
141 | |||
142 | /** |
||
143 | * @var Manager |
||
144 | */ |
||
145 | protected $oauthManager; |
||
146 | |||
147 | /** |
||
148 | * @var ClientRequestInterface[] |
||
149 | */ |
||
150 | protected $batchRequests = []; |
||
151 | |||
152 | protected $tokenRefreshed = false; |
||
153 | |||
154 | /** |
||
155 | * @param array|Config $config |
||
156 | * @param $cache |
||
157 | * @param LoggerInterface $logger |
||
158 | */ |
||
159 | 62 | public function __construct($config, $cache = null, LoggerInterface $logger = null) |
|
160 | { |
||
161 | 62 | parent::__construct($config); |
|
162 | |||
163 | 62 | $manager = new Manager($config, $cache); |
|
164 | 62 | $this->setOauthManager($manager); |
|
165 | 62 | $this->setLogger($logger); |
|
166 | 62 | } |
|
167 | |||
168 | /** |
||
169 | * @return Manager |
||
170 | */ |
||
171 | 35 | public function getOauthManager() |
|
172 | { |
||
173 | 35 | return $this->oauthManager; |
|
174 | } |
||
175 | |||
176 | /** |
||
177 | * @param Manager $oauthManager |
||
178 | * @return $this |
||
179 | */ |
||
180 | 62 | protected function setOauthManager(Manager $oauthManager) |
|
181 | { |
||
182 | 62 | $this->oauthManager = $oauthManager; |
|
183 | 62 | return $this; |
|
184 | } |
||
185 | |||
186 | /** |
||
187 | * @param LoggerInterface $logger |
||
188 | * @return $this |
||
189 | */ |
||
190 | 62 | public function setLogger(LoggerInterface $logger = null) |
|
191 | { |
||
192 | 62 | if ($logger instanceof LoggerInterface) { |
|
193 | 41 | $this->logger = $logger; |
|
194 | } |
||
195 | 62 | return $this; |
|
1 ignored issue
–
show
|
|||
196 | } |
||
197 | |||
198 | /** |
||
199 | * @param array $options |
||
200 | * @return AdapterInterface |
||
201 | */ |
||
202 | 563 | public function getHttpClient($options = []) |
|
203 | { |
||
204 | 563 | if (is_null($this->httpClient)) { |
|
205 | 60 | $clientOptions = $this->config->getClientOptions(); |
|
206 | 60 | if (count($clientOptions)) { |
|
207 | $options = array_merge($clientOptions, $options); |
||
208 | } |
||
209 | 60 | $client = parent::getHttpClient($options); |
|
210 | 60 | if ($client instanceof TokenProviderAware) { |
|
211 | 60 | $client->setOAuthTokenProvider($this->getOauthManager()); |
|
212 | } |
||
213 | 60 | if ($this->logger instanceof LoggerInterface) { |
|
1 ignored issue
–
show
|
|||
214 | 41 | $client->setLogger( |
|
215 | 41 | $this->logger, |
|
216 | 41 | $this->getConfig()->getLogLevel(), |
|
217 | 41 | $this->getConfig()->getMessageFormatter() |
|
218 | ); |
||
219 | } |
||
220 | 60 | if ($this->getConfig()->getCorrelationIdProvider() instanceof CorrelationIdProvider |
|
221 | 60 | && $client instanceof CorrelationIdAware |
|
222 | ) { |
||
223 | 59 | $client->setCorrelationIdProvider($this->getConfig()->getCorrelationIdProvider()); |
|
224 | } |
||
225 | 60 | $this->httpClient = $client; |
|
226 | } |
||
227 | |||
228 | 563 | return $this->httpClient; |
|
229 | } |
||
230 | |||
231 | |||
232 | /** |
||
233 | * @return string |
||
234 | */ |
||
235 | 61 | protected function getBaseUrl() |
|
236 | { |
||
237 | 61 | return $this->getConfig()->getApiUrl() . '/' . $this->getConfig()->getProject() . '/'; |
|
238 | } |
||
239 | |||
240 | /** |
||
241 | * Executes an API request synchronously |
||
242 | * |
||
243 | * @param ClientRequestInterface $request |
||
244 | * @param array $headers |
||
245 | * @param array $clientOptions |
||
246 | * @return ApiResponseInterface |
||
247 | * @throws ApiException |
||
248 | * @throws InvalidTokenException |
||
249 | */ |
||
250 | 555 | public function execute(ClientRequestInterface $request, array $headers = null, array $clientOptions = []) |
|
251 | { |
||
252 | 555 | if ($request instanceof ContextAwareInterface) { |
|
253 | 555 | $request->setContextIfNull($this->getConfig()->getContext()); |
|
254 | } |
||
255 | 555 | $httpRequest = $this->createHttpRequest($request, $headers); |
|
256 | |||
257 | try { |
||
258 | 555 | $client = $this->getHttpClient(); |
|
259 | 555 | if ($client instanceof AdapterOptionInterface) { |
|
260 | 555 | $httpResponse = $client->execute($httpRequest, $clientOptions); |
|
261 | } else { |
||
262 | $httpResponse = $client->execute($httpRequest); |
||
263 | } |
||
264 | 531 | $response = $request->buildResponse($httpResponse); |
|
265 | 81 | } catch (ApiException $exception) { |
|
266 | 81 | if ($exception instanceof InvalidTokenException && !$this->tokenRefreshed) { |
|
267 | 3 | $this->tokenRefreshed = true; |
|
268 | 3 | $this->getOauthManager()->refreshToken(); |
|
269 | 2 | return $this->execute($request); |
|
270 | } |
||
271 | 79 | if ($this->getConfig()->getThrowExceptions() || !$exception->getResponse() instanceof ResponseInterface) { |
|
272 | 10 | throw $exception; |
|
273 | } |
||
274 | 69 | $httpResponse = $exception->getResponse(); |
|
275 | 69 | $this->logException($exception); |
|
276 | 69 | $response = new ErrorResponse($exception, $request, $httpResponse); |
|
277 | } |
||
278 | 545 | $this->logDeprecatedRequest($httpResponse, $httpRequest); |
|
279 | |||
280 | |||
281 | 545 | return $response; |
|
282 | } |
||
283 | |||
284 | /** |
||
285 | * Executes an API request asynchronously |
||
286 | * @param ClientRequestInterface $request |
||
287 | * @param array $clientOptions |
||
288 | * @return ApiResponseInterface |
||
289 | */ |
||
290 | 2 | public function executeAsync(ClientRequestInterface $request, array $headers = null, array $clientOptions = []) |
|
291 | { |
||
292 | 2 | if ($request instanceof ContextAwareInterface) { |
|
293 | 2 | $request->setContextIfNull($this->getConfig()->getContext()); |
|
294 | } |
||
295 | 2 | $httpRequest = $this->createHttpRequest($request, $headers); |
|
296 | 2 | $client = $this->getHttpClient(); |
|
297 | 2 | if ($client instanceof AdapterOptionInterface) { |
|
298 | 2 | $response = $request->buildResponse($client->executeAsync($httpRequest, $clientOptions)); |
|
299 | } else { |
||
300 | $response = $request->buildResponse($client->executeAsync($httpRequest)); |
||
301 | } |
||
302 | |||
303 | 2 | $response = $response->then( |
|
304 | 2 | function ($httpResponse) use ($httpRequest) { |
|
305 | 2 | $this->logDeprecatedRequest($httpResponse, $httpRequest); |
|
306 | 2 | return $httpResponse; |
|
307 | 2 | } |
|
308 | ); |
||
309 | |||
310 | 2 | return $response; |
|
311 | } |
||
312 | |||
313 | /** |
||
314 | * @param ClientRequestInterface $request |
||
315 | * @param array $headers |
||
316 | * @return RequestInterface |
||
317 | */ |
||
318 | 562 | protected function createHttpRequest(ClientRequestInterface $request, array $headers = null) |
|
319 | { |
||
320 | 562 | $httpRequest = $request->httpRequest(); |
|
321 | 562 | if (!$this->getHttpClient() instanceof TokenProviderAware) { |
|
322 | $token = $this->getOauthManager()->getToken(); |
||
323 | $httpRequest = $httpRequest |
||
324 | ->withHeader('Authorization', 'Bearer ' . $token->getToken()) |
||
325 | ; |
||
326 | } |
||
327 | 562 | if (is_array($headers)) { |
|
328 | 2 | foreach ($headers as $headerName => $headerValues) { |
|
329 | $httpRequest = $httpRequest |
||
330 | 2 | ->withAddedHeader($headerName, $headerValues) |
|
331 | ; |
||
332 | } |
||
333 | } |
||
334 | |||
335 | 562 | return $httpRequest; |
|
336 | } |
||
337 | |||
338 | /** |
||
339 | * Executes API requests in batch |
||
340 | * @param array $headers |
||
341 | * @param array $clientOptions |
||
342 | * @return ApiResponseInterface[] |
||
343 | * @throws ApiException |
||
344 | */ |
||
345 | 467 | public function executeBatch(array $headers = null, array $clientOptions = []) |
|
346 | { |
||
347 | 467 | $requests = $this->getBatchHttpRequests($headers); |
|
348 | 467 | $client = $this->getHttpClient(); |
|
349 | 467 | if ($client instanceof AdapterOptionInterface) { |
|
350 | 467 | $httpResponses = $client->executeBatch($requests, $clientOptions); |
|
351 | } else { |
||
352 | $httpResponses = $client->executeBatch($requests); |
||
353 | } |
||
354 | |||
355 | 467 | $responses = []; |
|
356 | 467 | foreach ($httpResponses as $key => $httpResponse) { |
|
357 | 467 | $request = $this->batchRequests[$key]; |
|
358 | 467 | $httpRequest = $requests[$key]; |
|
359 | 467 | if ($httpResponse instanceof ApiException) { |
|
360 | 12 | $exception = $httpResponse; |
|
361 | 12 | if ($this->getConfig()->getThrowExceptions() || |
|
362 | 12 | !$httpResponse->getResponse() instanceof ResponseInterface |
|
363 | ) { |
||
364 | 1 | throw $exception; |
|
365 | } |
||
366 | 11 | $this->logException($httpResponse); |
|
367 | 11 | $httpResponse = $exception->getResponse(); |
|
368 | 11 | $responses[$request->getIdentifier()] = new ErrorResponse( |
|
369 | 11 | $exception, |
|
370 | 11 | $request, |
|
371 | 11 | $httpResponse |
|
372 | ); |
||
373 | } else { |
||
374 | 460 | $responses[$request->getIdentifier()] = $request->buildResponse($httpResponse); |
|
375 | } |
||
376 | 466 | $this->logDeprecatedRequest($httpResponse, $httpRequest); |
|
377 | } |
||
378 | 466 | unset($this->batchRequests); |
|
379 | 466 | $this->batchRequests = []; |
|
380 | |||
381 | 466 | return $responses; |
|
382 | } |
||
383 | |||
384 | /** |
||
385 | * @param $exception |
||
386 | * @return $this |
||
387 | */ |
||
388 | 80 | protected function logException(ApiException $exception) |
|
389 | { |
||
390 | 80 | if (is_null($this->logger)) { |
|
391 | 3 | return $this; |
|
392 | } |
||
393 | 77 | $response = $exception->getResponse(); |
|
394 | |||
395 | 77 | $context = []; |
|
396 | 77 | if ($response instanceof ResponseInterface) { |
|
1 ignored issue
–
show
|
|||
397 | $context = [ |
||
398 | 77 | 'responseStatusCode' => $response->getStatusCode(), |
|
399 | 77 | 'responseHeaders' => $response->getHeaders(), |
|
400 | 77 | 'responseBody' => (string)$response->getBody(), |
|
401 | ]; |
||
402 | } |
||
403 | 77 | $this->logger->error($exception->getMessage(), $context); |
|
404 | |||
405 | 77 | return $this; |
|
406 | } |
||
407 | |||
408 | /** |
||
409 | * @param ResponseInterface $response |
||
410 | * @param RequestInterface $request |
||
411 | * @return $this |
||
412 | */ |
||
413 | 551 | protected function logDeprecatedRequest(ResponseInterface $response, RequestInterface $request) |
|
414 | { |
||
415 | 551 | if (is_null($this->logger)) { |
|
416 | 7 | return $this; |
|
417 | } |
||
418 | |||
419 | 544 | if ($response->hasHeader(static::DEPRECATION_HEADER)) { |
|
420 | 3 | $message = sprintf( |
|
421 | 3 | Message::DEPRECATED_METHOD, |
|
422 | 3 | $request->getUri(), |
|
423 | 3 | $request->getMethod(), |
|
424 | 3 | $response->getHeaderLine(static::DEPRECATION_HEADER) |
|
425 | ); |
||
426 | 3 | $this->logger->warning($message); |
|
427 | } |
||
428 | 544 | return $this; |
|
429 | } |
||
430 | |||
431 | /** |
||
432 | * @param RequestInterface $request |
||
433 | * @param ResponseInterface $response |
||
434 | * @return string |
||
435 | */ |
||
436 | protected function format(RequestInterface $request, ResponseInterface $response) |
||
437 | { |
||
438 | $entries = [ |
||
439 | $request->getMethod(), |
||
440 | (string)$request->getUri(), |
||
441 | $response->getStatusCode() |
||
442 | ]; |
||
443 | return implode(', ', $entries); |
||
444 | } |
||
445 | |||
446 | /** |
||
447 | * @param array $headers |
||
448 | * @return array |
||
449 | */ |
||
450 | 467 | protected function getBatchHttpRequests(array $headers = null) |
|
451 | { |
||
452 | 467 | $requests = array_map( |
|
453 | 467 | function ($request) use ($headers) { |
|
454 | 467 | return $this->createHttpRequest($request, $headers); |
|
455 | 467 | }, |
|
456 | 467 | $this->batchRequests |
|
457 | ); |
||
458 | |||
459 | 467 | return $requests; |
|
460 | } |
||
461 | |||
462 | /** |
||
463 | * Adds a request to the batch execution queue |
||
464 | * @param ClientRequestInterface $request |
||
465 | * @return $this |
||
466 | */ |
||
467 | 467 | public function addBatchRequest(ClientRequestInterface $request) |
|
468 | { |
||
469 | 467 | if ($request instanceof ContextAwareInterface) { |
|
470 | 467 | $request->setContextIfNull($this->getConfig()->getContext()); |
|
471 | } |
||
472 | 467 | $this->batchRequests[] = $request; |
|
473 | 467 | return $this; |
|
474 | } |
||
475 | |||
476 | /** |
||
477 | * Instantiates a client with the given config |
||
478 | * @param Config $config |
||
479 | * @return static |
||
480 | */ |
||
481 | 1 | public static function ofConfig(Config $config) |
|
484 | } |
||
485 | |||
486 | /** |
||
487 | * Instantiates a client with the given config and cache adapter |
||
488 | * @param Config $config |
||
489 | * @param $cache |
||
490 | * @return static |
||
491 | */ |
||
492 | public static function ofConfigAndCache(Config $config, $cache) |
||
493 | { |
||
494 | return new static($config, $cache); |
||
495 | } |
||
496 | |||
497 | /** |
||
498 | * Instantiates a client with the given config and a PSR-3 compliant logger |
||
499 | * @param Config $config |
||
500 | * @param LoggerInterface $logger |
||
501 | * @return static |
||
502 | */ |
||
503 | 1 | public static function ofConfigAndLogger(Config $config, LoggerInterface $logger) |
|
506 | } |
||
507 | |||
508 | /** |
||
509 | * Instantiates a client with the given config, a cache adapter and a PSR-3 compliant logger |
||
510 | * @param Config $config |
||
511 | * @param $cache |
||
512 | * @param LoggerInterface $logger |
||
513 | * @return static |
||
514 | */ |
||
515 | 32 | public static function ofConfigCacheAndLogger(Config $config, $cache, LoggerInterface $logger) |
|
520 |
In the issue above, the returned value is violating the contract defined by the mentioned interface.
Let's take a look at an example: