ClientFactory   B
last analyzed

Complexity

Total Complexity 51

Size/Duplication

Total Lines 438
Duplicated Lines 0 %

Test Coverage

Coverage 88.96%

Importance

Changes 0
Metric Value
wmc 51
eloc 180
c 0
b 0
f 0
dl 0
loc 438
rs 7.92
ccs 145
cts 163
cp 0.8896

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 2
A log() 0 29 3
A httpErrors() 0 14 3
A of() 0 3 1
A getDefaultOptions() 0 14 3
A createConfig() 0 9 3
A isGuzzle6() 0 15 4
A setLogger() 0 10 2
A createClient() 0 16 1
A createAuthClient() 0 19 3
A addMiddlewares() 0 15 6
A createGuzzle6Client() 0 49 5
A reauthenticate() 0 28 5
A setCorrelationIdMiddleware() 0 11 2
A getHandler() 0 18 2
B createCustomClient() 0 49 6

How to fix   Complexity   

Complex Class

Complex classes like ClientFactory 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 ClientFactory, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Commercetools\Core\Client;
4
5
use Commercetools\Core\Cache\CacheAdapterFactory;
6
use Commercetools\Core\Client\OAuth\CacheTokenProvider;
7
use Commercetools\Core\Client\OAuth\ClientCredentials;
8
use Commercetools\Core\Client\OAuth\CredentialTokenProvider;
9
use Commercetools\Core\Client\OAuth\OAuth2Handler;
10
use Commercetools\Core\Client\OAuth\TokenProvider;
11
use Commercetools\Core\Config;
12
use Commercetools\Core\Error\ApiException;
13
use Commercetools\Core\Error\DeprecatedException;
14
use Commercetools\Core\Error\InvalidTokenException;
15
use Commercetools\Core\Error\Message;
16
use Commercetools\Core\Helper\CorrelationIdProvider;
17
use Commercetools\Core\Error\InvalidArgumentException;
18
use Commercetools\Core\Model\Common\Context;
19
use Commercetools\Core\Model\Common\ContextAwareInterface;
20
use Commercetools\Core\Response\AbstractApiResponse;
21
use GuzzleHttp\Client;
22
use GuzzleHttp\Client as HttpClient;
23
use GuzzleHttp\Exception\RequestException;
24
use GuzzleHttp\HandlerStack;
25
use GuzzleHttp\MessageFormatter;
26
use GuzzleHttp\Middleware;
27
use Psr\Cache\CacheItemPoolInterface;
28
use Psr\Http\Message\RequestInterface;
29
use Psr\Http\Message\ResponseInterface;
30
use Psr\Log\LoggerInterface;
31
use Psr\Log\LogLevel;
32
use Psr\SimpleCache\CacheInterface;
33
34
/**
35
 * The factory to create a Client for communicating with the commercetools platform
36
 *
37
 * @description
38
 * This factory will create a Guzzle HTTP Client preconfigured for talking to the commercetools platform
39
 *
40
 * ## Instantiation
41
 *
42
 * ```php
43
 * $config = Config::fromArray(
44
 *  ['client_id' => '<client_id>', 'client_secret' => '<client_secret>', 'project' => '<project>']
45
 * );
46
 * $client = ClientFactory::of()->createClient($config);
47
 * ```
48
 *
49
 * ## Execution
50
 *
51
 * ### Synchronous
52
 *
53
 * ```php
54
 * $request = ProductProjectionSearchRequest::of();
55
 * $response = $client->execute($request);
56
 * $products = $request->mapFromResponse($response);
57
 * ```
58
 *
59
 * ### Asynchronous
60
 * The asynchronous execution will return a promise to fulfill the request.
61
 *
62
 * ```php
63
 * $request = ProductProjectionSearchRequest::of();
64
 * $response = $client->executeAsync($request);
65
 * $products = $request->mapFromResponse($response->wait());
66
 * ```
67
 *
68
 * ### Batch
69
 * By filling the batch queue and starting the execution all requests will be executed in parallel.
70
 *
71
 * ```php
72
 * $responses = Pool::batch(
73
 *     $client,
74
 *     [ProductProjectionSearchRequest::of()->httpRequest(), CartByIdGetRequest::ofId($cartId)->httpRequest()]
75
 * );
76
 * ```
77
 *
78
 * ## Instantiation options
79
 *
80
 * ### Using a logger
81
 *
82
 * The client uses the PSR-3 logger interface for logging requests and deprecation notices. To enable
83
 * logging provide a PSR-3 compliant logger (e.g. Monolog).
84
 *
85
 * ```php
86
 * $logger = new \Monolog\Logger('name');
87
 * $logger->pushHandler(new StreamHandler('./requests.log'));
88
 * $client = ClientFactory::of()->createClient($config, $logger);
89
 * ```
90
 *
91
 * ### Using a cache adapter ###
92
 *
93
 * The client will automatically request an OAuth token and store the token in the provided cache.
94
 *
95
 * It's also possible to use a different cache adapter. The SDK provides a Doctrine, a Redis and an APCu cache adapter.
96
 * By default the SDK tries to instantiate the APCu or a PSR-6 filesystem cache adapter if there is no cache given.
97
 * E.g. Redis:
98
 *
99
 * ```php
100
 * $redis = new \Redis();
101
 * $redis->connect('localhost');
102
 * $client = ClientFactory::of()->createClient($config, null, $cache);
103
 * ```
104
 *
105
 * #### Using cache and logger ####
106
 *
107
 * ```php
108
 * $client = ClientFactory::of()->createClient($config, $logger, $cache);
109
 * ```
110
 *
111
 * #### Using a custom cache adapter ####
112
 *
113
 * ```php
114
 * class <CacheClass>Adapter implements \Psr\Cache\CacheItemPoolInterface {
115
 *     protected $cache;
116
 *     public function __construct(<CacheClass> $cache) {
117
 *         $this->cache = $cache;
118
 *     }
119
 * }
120
 *
121
 * $client->getAdapterFactory()->registerCallback(function ($cache) {
122
 *     if ($cache instanceof <CacheClass>) {
123
 *         return new <CacheClass>Adapter($cache);
124
 *     }
125
 *     return null;
126
 * });
127
 * ```
128
 *
129
 * ### Using a custom client class
130
 *
131
 * If some additional configuration is needed or the client should have custom logic you could provide a class name
132
 * to be used for the client instance. This class has to be an extended Guzzle client.
133
 *
134
 * ```php
135
 * $client = ClientFactory::of()->createCustomClient(MyCustomClient::class, $config);
136
 * ```
137
 *
138
 * ## Middlewares
139
 *
140
 * Adding middlewares to the clients for platform as well for the authentication can be done using the config
141
 * by setting client options.
142
 *
143
 * ### Using a HandlerStack
144
 *
145
 * ```php
146
 * $handler = HandlerStack::create();
147
 * $handler->push(Middleware::mapRequest(function (RequestInterface $request) {
148
 *     ...
149
 *     return $request; })
150
 * );
151
 * $config = Config::of()->setClientOptions(['handler' => $handler])
152
 * ```
153
 *
154
 * ### Using a middleware array
155
 *
156
 * ```php
157
 * $middlewares = [
158
 *     Middleware::mapRequest(function (RequestInterface $request) {
159
 *     ...
160
 *     return $request; }),
161
 *     ...
162
 * ]
163
 * $config = Config::of()->setClientOptions(['middlewares' => $middlewares])
164
 * ```
165
 *
166
 * ### Timeouts
167
 *
168
 * The clients are configured to timeout by default after 60 seconds. This can be changed by setting the client options in the Config instance
169
 *
170
 * ```php
171
 * $config = Config::of()->setClientOptions([
172
 *     'defaults' => [
173
 *         'timeout' => 10
174
 *     ]
175
 * ])
176
 * ```
177
 *
178
 * Another option is to specify the timeout per request
179 28
 *
180
 * ```php
181 28
 * $request = ProductProjectionSearchRequest::of();
182
 * $response = $client->execute($request, null, ['timeout' => 10]);
183
 * ```
184 28
 *
185
 * ### Retrying
186
 *
187
 * As a request can error in multiple ways it's possible to add a retry middleware to the client config. E.g.: Retrying in case of service unavailable errors
188
 *
189
 * ```php
190
 * $config = Config::of()->setClientOptions([
191
 *     'defaults' => [
192
 *         'timeout' => 10
193
 *     ]
194
 * ])
195
 * $maxRetries = 3;
196 27
 * $clientOptions = [
197
 *     'middlewares' => [
198
 *         'retry' => Middleware::retry(
199
 *             function ($retries, RequestInterface $request, ResponseInterface $response = null, $error = null) use ($maxRetries) {
200
 *                 if ($response instanceof ResponseInterface && $response->getStatusCode() < 500) {
201
 *                     return false;
202
 *                 }
203
 *                 if ($retries > $maxRetries) {
204
 *                     return false;
205 27
 *                 }
206
 *                 if ($error instanceof ServiceUnavailableException) {
207 27
 *                     return true;
208 27
 *                 }
209
 *                 if ($error instanceof ServerException && $error->getCode() == 503) {
210 27
 *                     return true;
211 27
 *                 }
212 27
 *                 if ($response instanceof ResponseInterface && $response->getStatusCode() == 503) {
213 27
 *                     return true;
214
 *                 }
215
 *                 return false;
216 27
 *             },
217 27
 *             [RetryMiddleware::class, 'exponentialDelay']
218
 *         )
219
 *     ]
220
 * ];
221 27
 * $config->setClientOptions($clientOptions);
222 27
 * ```
223 27
 * @package Commercetools\Core\Client
224 27
 */
225
class ClientFactory
226
{
227 27
    /**
228 27
     * @var bool
229
     */
230
    private static $isGuzzle6;
231 27
232
    /**
233 27
     * ClientFactory constructor.
234 27
     * @throws DeprecatedException
235
     */
236
    public function __construct()
237
    {
238 27
        if (!self::isGuzzle6()) {
239
            throw new DeprecatedException("ClientFactory doesn't support Guzzle version < 6");
240
        }
241 27
    }
242 26
243
    /**
244 27
     * @param string $clientClass
245
     * @param Config|array $config
246
     * @param LoggerInterface $logger
247
     * @param CacheItemPoolInterface|CacheInterface $cache
248
     * @param TokenProvider $provider
249
     * @param CacheAdapterFactory $cacheAdapterFactory
250
     * @param Context|null $context
251
     * @return Client
252
     */
253
    public function createCustomClient(
254
        $clientClass,
255
        $config,
256 25
        LoggerInterface $logger = null,
257
        $cache = null,
258
        TokenProvider $provider = null,
259
        CacheAdapterFactory $cacheAdapterFactory = null,
260
        Context $context = null
261
    ) {
262
        $config = $this->createConfig($config);
263
264 25
        if (is_null($context)) {
265 25
            $context = $config->getContext();
266
        }
267
        if (is_null($cacheAdapterFactory)) {
268
            $cacheDir = $config->getCacheDir();
269
            $cacheDir = !is_null($cacheDir) ? $cacheDir : realpath(__DIR__ . '/../../..');
0 ignored issues
show
introduced by
The condition is_null($cacheDir) is always false.
Loading history...
270
            $cacheAdapterFactory = new CacheAdapterFactory($cacheDir);
271
        }
272
273
        $cache = $cacheAdapterFactory->get($cache);
274
        if (is_null($cache)) {
275 14
            throw new InvalidArgumentException(Message::INVALID_CACHE_ADAPTER);
276
        }
277
278
        $credentials = $config->getClientCredentials();
279 14
        $oauthHandler = $this->getHandler(
280
            $credentials,
281
            $config->getOauthUrl(),
282 14
            $cache,
283 14
            $provider,
284
            $config->getOAuthClientOptions(),
285
            $config->getCorrelationIdProvider()
286 14
        );
287 14
288
        $options = $this->getDefaultOptions($config);
289 14
290
        $client = $this->createGuzzle6Client(
291 14
            $clientClass,
292
            $options,
293 14
            $oauthHandler,
294
            $logger,
295
            $config->getCorrelationIdProvider()
296 27
        );
297
298 27
        if ($client instanceof ContextAwareInterface) {
299 27
            $client->setContext($context);
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\Client::__call() has been deprecated: Client::__call will be removed in guzzlehttp/guzzle:8.0. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

299
            /** @scrutinizer ignore-deprecated */ $client->setContext($context);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
300 27
        }
301
        return $client;
302 27
    }
303
304 27
    /**
305 27
     * @param Config|array $config
306
     * @param LoggerInterface $logger
307 27
     * @param CacheItemPoolInterface|CacheInterface $cache
308
     * @param TokenProvider $provider
309 27
     * @param CacheAdapterFactory $cacheAdapterFactory
310
     * @param Context|null $context
311
     * @return ApiClient
312
     */
313
    public function createClient(
314
        $config,
315
        LoggerInterface $logger = null,
316
        $cache = null,
317 27
        TokenProvider $provider = null,
318
        CacheAdapterFactory $cacheAdapterFactory = null,
319 27
        Context $context = null
320 27
    ) {
321
        return $this->createCustomClient(
322
            ApiClient::class,
323
            $config,
324
            $logger,
325
            $cache,
326
            $provider,
327
            $cacheAdapterFactory,
328
            $context
329
        );
330
    }
331
332
    public function createAuthClient(
333
        array $options = [],
334
        CorrelationIdProvider $correlationIdProvider = null
335
    ) {
336 27
        if (isset($options['handler']) && $options['handler'] instanceof HandlerStack) {
337
            $handler = $options['handler'];
338
        } else {
339
            $handler = HandlerStack::create();
340
            $options['handler'] = $handler;
341
        }
342
343 27
        $handler->remove("http_errors");
344
        $handler->unshift(self::httpErrors(), 'ctp_http_errors');
345
346 27
        $this->setCorrelationIdMiddleware($handler, $correlationIdProvider);
347 27
348
        $options = $this->addMiddlewares($handler, $options);
349
350 27
        return new Client($options);
351
    }
352 27
353
    private function getDefaultOptions(Config $config)
354
    {
355
        $options = $config->getClientOptions();
356
        $options['http_errors'] = $config->getThrowExceptions();
357
        $options['base_uri'] = $config->getApiUrl() . "/" . $config->getProject() . "/";
358
        $defaultHeaders = [
359
            'User-Agent' => (new UserAgentProvider())->getUserAgent()
360
        ];
361 27
        if (!is_null($config->getAcceptEncoding())) {
0 ignored issues
show
introduced by
The condition is_null($config->getAcceptEncoding()) is always false.
Loading history...
362 23
            $defaultHeaders['Accept-Encoding'] = $config->getAcceptEncoding();
363
        }
364
        $options['headers'] = array_merge($defaultHeaders, (isset($options['headers']) ? $options['headers'] : []));
365 27
366 27
        return $options;
367
    }
368 27
369 27
    /**
370 27
     * @param Config|array $config
371
     * @return Config
372 27
     * @throws InvalidArgumentException
373 26
     */
374 26
    private function createConfig($config)
375 26
    {
376
        if ($config instanceof Config) {
377
            return $config;
378
        }
379 27
        if (is_array($config)) {
0 ignored issues
show
introduced by
The condition is_array($config) is always true.
Loading history...
380 27
            return Config::fromArray($config);
381
        }
382 27
        throw new InvalidArgumentException();
383
    }
384 27
385
    /**
386
     * @param string $clientClass
387 23
     * @param array $options
388
     * @param OAuth2Handler $oauthHandler
389
     * @param LoggerInterface|null $logger
390
     * @param CorrelationIdProvider|null $correlationIdProvider
391
     * @return Client
392
     */
393 23
    private function createGuzzle6Client(
394 23
        $clientClass,
395
        array $options,
396 23
        OAuth2Handler $oauthHandler,
397 23
        LoggerInterface $logger = null,
398
        CorrelationIdProvider $correlationIdProvider = null
399
    ) {
400
        if (isset($options['handler']) && $options['handler'] instanceof HandlerStack) {
401
            $handler = $options['handler'];
402
        } else {
403 704
            $handler = HandlerStack::create();
404
            $options['handler'] = $handler;
405
        }
406
407 27
        $options = array_merge(
408 704
            [
409 702
                'allow_redirects' => false,
410 702
                'verify' => true,
411 702
                'timeout' => 60,
412
                'connect_timeout' => 10,
413 27
                'pool_size' => 25,
414
            ],
415 27
            $options
416
        );
417
418
        if (!is_null($logger)) {
419
            $this->setLogger($handler, $logger);
420
        }
421
422 27
        $handler->remove("http_errors");
423
        $handler->unshift(self::httpErrors(), 'ctp_http_errors');
424 27
425 4
        $handler->push(
426 4
            Middleware::mapRequest($oauthHandler),
427 4
            'oauth_2_0'
428 4
        );
429 4
        if ($oauthHandler->refreshable()) {
430
            $handler->push(
431
                self::reauthenticate($oauthHandler),
432
                'reauthenticate'
433
            );
434
        }
435
436 27
        $this->setCorrelationIdMiddleware($handler, $correlationIdProvider);
437
        $options = $this->addMiddlewares($handler, $options);
438
439
        $client = new $clientClass($options);
440
441
        return $client;
442
    }
443
444
    private function setLogger(
445
        HandlerStack $handler,
446 701
        LoggerInterface $logger,
447
        $logLevel = LogLevel::INFO,
448 26
        $formatter = null
449 701
    ) {
450 700
        if (is_null($formatter)) {
451 700
            $formatter = new MessageFormatter();
452 700
        }
453 700
        $handler->push(self::log($logger, $formatter, $logLevel), 'ctp_logger');
454 700
    }
455 700
456 700
    /**
457
     * @param CorrelationIdProvider $correlationIdProvider
458 700
     * @param HandlerStack $handler
459 1
     */
460 1
    private function setCorrelationIdMiddleware(
461
        HandlerStack $handler,
462 1
        CorrelationIdProvider $correlationIdProvider = null
463 1
    ) {
464 1
        if (!is_null($correlationIdProvider)) {
465 1
            $handler->push(Middleware::mapRequest(function (RequestInterface $request) use ($correlationIdProvider) {
466 1
                return $request->withAddedHeader(
467 1
                    AbstractApiResponse::X_CORRELATION_ID,
468 1
                    $correlationIdProvider->getCorrelationId()
469
                );
470 1
            }), 'ctp_correlation_id');
471
        }
472
    }
473 699
474 700
    /**
475
     * @param HandlerStack $handler
476 24
     * @param array $options
477 26
     * @return array
478
     */
479
    private function addMiddlewares(HandlerStack $handler, array $options)
480
    {
481
        if (isset($options['middlewares']) && is_array($options['middlewares'])) {
482
            foreach ($options['middlewares'] as $key => $middleware) {
483
                if (is_callable($middleware)) {
484
                    if (!is_numeric($key)) {
485
                        $handler->remove($key);
486 702
                        $handler->push($middleware, $key);
487
                    } else {
488 27
                        $handler->push($middleware);
489 702
                    }
490 702
                }
491 20
            }
492
        }
493 684
        return $options;
494 684
    }
495 684
496 684
    /**
497 674
     * Middleware that reauthenticates on invalid token error
498
     *
499 214
     * @param OAuth2Handler $oauthHandler
500 684
     * @param int $maxRetries
501
     * @return callable Returns a function that accepts the next handler.
502 25
     */
503 27
    public static function reauthenticate(OAuth2Handler $oauthHandler, $maxRetries = 1)
504
    {
505
        return function (callable $handler) use ($oauthHandler, $maxRetries) {
506
            return function (RequestInterface $request, array $options) use ($handler, $oauthHandler, $maxRetries) {
507
                return $handler($request, $options)->then(
508
                    function (ResponseInterface $response) use (
509
                        $request,
510
                        $handler,
511
                        $oauthHandler,
512
                        $options,
513
                        $maxRetries
514
                    ) {
515 27
                        if ($response->getStatusCode() == 401) {
516
                            if (!isset($options['reauth'])) {
517
                                $options['reauth'] = 0;
518
                            }
519
                            $exception = ApiException::create($request, $response);
520
                            if ($options['reauth'] < $maxRetries && $exception instanceof InvalidTokenException) {
521
                                $options['reauth']++;
522
                                $token = $oauthHandler->refreshToken();
523 27
                                $request = $request->withHeader(
524 14
                                    'Authorization',
525 14
                                    'Bearer ' . $token->getToken()
526
                                );
527
                                return $handler($request, $options);
528
                            }
529 14
                        }
530 14
                        return $response;
531
                    }
532 27
                );
533
            };
534
        };
535
    }
536
537
    /**
538
     * Middleware that throws exceptions for 4xx or 5xx responses when the
539
     * "http_error" request option is set to true.
540
     *
541
     * @return callable Returns a function that accepts the next handler.
542
     */
543
    public static function httpErrors()
544
    {
545 700
        return function (callable $handler) {
546
            return function ($request, array $options) use ($handler) {
547 23
                if (empty($options['http_errors'])) {
548 700
                    return $handler($request, $options);
549 700
                }
550 700
                return $handler($request, $options)->then(
551 700
                    function (ResponseInterface $response) use ($request, $handler) {
0 ignored issues
show
Unused Code introduced by
The import $handler is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
552
                        $code = $response->getStatusCode();
553 700
                        if ($code < 400) {
554 700
                            return $response;
555
                        }
556
                        throw ApiException::create($request, $response);
557 700
                    }
558 700
                );
559 700
            };
560 700
        };
561
    }
562
563
    /**
564
     * @param ClientCredentials $credentials
565
     * @param string $accessTokenUrl
566
     * @param CacheItemPoolInterface|CacheInterface $cache
567
     * @param TokenProvider $provider
568
     * @param array $authClientOptions
569
     * @param CorrelationIdProvider|null $correlationIdProvider
570
     * @return OAuth2Handler
571
     */
572
    private function getHandler(
573
        ClientCredentials $credentials,
574 700
        $accessTokenUrl,
575
        $cache,
576 23
        TokenProvider $provider = null,
577 23
        array $authClientOptions = [],
578
        CorrelationIdProvider $correlationIdProvider = null
579
    ) {
580
        if (is_null($provider)) {
581
            $provider = new CredentialTokenProvider(
582
                $this->createAuthClient($authClientOptions, $correlationIdProvider),
583 28
                $accessTokenUrl,
584
                $credentials
585 28
            );
586 1
            $cacheKey = sha1($credentials->getClientId() . $credentials->getScope());
587 1
            $provider = new CacheTokenProvider($provider, $cache, $cacheKey);
588
        }
589
        return new OAuth2Handler($provider);
590
    }
591 1
592 1
    /**
593
     * Middleware that logs requests, responses, and errors using a message
594
     * formatter.
595
     *
596
     * @param LoggerInterface  $logger Logs messages.
597 28
     * @param MessageFormatter $formatter Formatter used to create message strings.
598
     * @param string           $logLevel Level at which to log requests.
599
     *
600
     * @return callable Returns a function that accepts the next handler.
601
     */
602
    private static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO)
603 28
    {
604
        return function (callable $handler) use ($logger, $formatter, $logLevel) {
605 28
            return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
606
                return $handler($request, $options)->then(
607
                    function (ResponseInterface $response) use ($logger, $request, $formatter, $logLevel) {
608
                        $message = $formatter->format($request, $response);
609
                        $context = [
610
                            AbstractApiResponse::X_CORRELATION_ID => $response->getHeader(
611
                                AbstractApiResponse::X_CORRELATION_ID
612
                            )
613
                        ];
614
                        $logger->log($logLevel, $message, $context);
615
                        return $response;
616
                    },
617
                    function ($reason) use ($logger, $request, $formatter) {
618
                        $response = null;
619
                        $context = [];
620
                        if ($reason instanceof RequestException) {
621
                            $response = $reason->getResponse();
622
                            if (!is_null($response)) {
623
                                $context[AbstractApiResponse::X_CORRELATION_ID] = $response->getHeader(
624
                                    AbstractApiResponse::X_CORRELATION_ID
625
                                );
626
                            }
627
                        }
628
                        $message = $formatter->format($request, $response, $reason);
629
                        $logger->notice($message, $context);
630
                        return \GuzzleHttp\Promise\rejection_for($reason);
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\Promise\rejection_for() has been deprecated: rejection_for will be removed in guzzlehttp/promises:2.0. Use Create::rejectionFor instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

630
                        return /** @scrutinizer ignore-deprecated */ \GuzzleHttp\Promise\rejection_for($reason);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
631
                    }
632
                );
633
            };
634
        };
635
    }
636
637
    /**
638
     * @return bool
639
     */
640
    private static function isGuzzle6()
641
    {
642
        if (is_null(self::$isGuzzle6)) {
0 ignored issues
show
introduced by
The condition is_null(self::isGuzzle6) is always false.
Loading history...
643
            if (defined('\GuzzleHttp\Client::MAJOR_VERSION')) {
644
                $clientVersion = (string) constant(HttpClient::class . '::MAJOR_VERSION');
645
            } else {
646
                $clientVersion = (string) constant(HttpClient::class . '::VERSION');
647
            }
648
            if (version_compare($clientVersion, '6.0.0', '>=')) {
649
                self::$isGuzzle6 = true;
650
            } else {
651
                self::$isGuzzle6 = false;
652
            }
653
        }
654
        return self::$isGuzzle6;
655
    }
656
657
    /**
658
     * @return ClientFactory
659
     */
660
    public static function of()
661
    {
662
        return new static();
663
    }
664
}
665