| 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: