Test Failed
Pull Request — develop (#455)
by nikos
12:50
created

Guzzle6Adapter::log()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 29
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 3.009

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 29
ccs 18
cts 20
cp 0.9
rs 9.584
c 0
b 0
f 0
cc 3
nc 1
nop 3
crap 3.009
1
<?php
2
/**
3
 * @author @jenschude <[email protected]>
4
 */
5
6
namespace Commercetools\Core\Client\Adapter;
7
8
use Commercetools\Core\Client\OAuth\TokenProvider;
9
use Commercetools\Core\Helper\CorrelationIdProvider;
10
use Commercetools\Core\Response\AbstractApiResponse;
11
use GuzzleHttp\Client;
12
use GuzzleHttp\Exception\RequestException;
13
use GuzzleHttp\MessageFormatter;
14
use GuzzleHttp\Middleware;
15
use GuzzleHttp\Pool;
16
use Psr\Http\Message\RequestInterface;
17
use Psr\Http\Message\ResponseInterface;
18
use Psr\Log\LoggerInterface;
19
use Commercetools\Core\Error\ApiException;
20
use Psr\Log\LogLevel;
21
22
class Guzzle6Adapter implements AdapterOptionInterface, CorrelationIdAware, TokenProviderAware, ConfigAware
23
{
24
    const DEFAULT_CONCURRENCY = 25;
25
    /**
26
     * @var Client
27
     */
28
    protected $client;
29
30
    protected $logger;
31
32
    private $concurrency;
33
34 115
    public function __construct(array $options = [])
35
    {
36 115
        $options = array_merge(
37
            [
38 115
                'allow_redirects' => false,
39
                'verify' => true,
40 115
                'timeout' => 60,
41 115
                'connect_timeout' => 10,
42 115
                'concurrency' => self::DEFAULT_CONCURRENCY
43
            ],
44 115
            $options
45
        );
46 115
        $this->concurrency = $options['concurrency'];
47 115
        $this->client = new Client($options);
48 115
    }
49
50 45
    public function setLogger(LoggerInterface $logger, $logLevel = LogLevel::INFO, $formatter = null)
51
    {
52 45
        if (is_null($formatter)) {
53 45
            $formatter = new MessageFormatter();
54
        }
55 45
        $this->logger = $logger;
56 45
        $this->addHandler(self::log($logger, $formatter, $logLevel));
57 45
    }
58
59
    public function setCorrelationIdProvider(CorrelationIdProvider $provider)
60
    {
61 709
        $this->addHandler(Middleware::mapRequest(function (RequestInterface $request) use ($provider) {
62 709
            return $request->withAddedHeader(
63 709
                AbstractApiResponse::X_CORRELATION_ID,
64 709
                $provider->getCorrelationId()
65
            );
66 76
        }));
67 76
    }
68
69
    public function setOAuthTokenProvider(TokenProvider $tokenProvider)
70
    {
71 702
        $this->addHandler(Middleware::mapRequest(function (RequestInterface $request) use ($tokenProvider) {
72 702
            return $request->withAddedHeader(
73 702
                'Authorization',
74 702
                'Bearer ' . $tokenProvider->getToken()->getToken()
75
            );
76 61
        }));
77 61
    }
78
79
    /**
80
     * Middleware that logs requests, responses, and errors using a message
81
     * formatter.
82
     *
83
     * @param LoggerInterface  $logger Logs messages.
84
     * @param MessageFormatter $formatter Formatter used to create message strings.
85
     * @param string           $logLevel Level at which to log requests.
86
     *
87
     * @return callable Returns a function that accepts the next handler.
88
     */
89
    private static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO)
90
    {
91
        return function (callable $handler) use ($logger, $formatter, $logLevel) {
92 684
            return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
93 684
                return $handler($request, $options)->then(
94 684
                    function ($response) use ($logger, $request, $formatter, $logLevel) {
95 684
                        $message = $formatter->format($request, $response);
96
                        $context = [
97 684
                            AbstractApiResponse::X_CORRELATION_ID => $response->getHeader(
98 684
                                AbstractApiResponse::X_CORRELATION_ID
99
                            )
100
                        ];
101 684
                        $logger->log($logLevel, $message, $context);
102 684
                        return $response;
103 684
                    },
104 684
                    function ($reason) use ($logger, $request, $formatter) {
105 1
                        $response = null;
106 1
                        $context = [];
107 1
                        if ($reason instanceof RequestException) {
108 1
                            $response = $reason->getResponse();
109 1
                            if (!is_null($response)) {
110
                                $context[AbstractApiResponse::X_CORRELATION_ID] = $response->getHeader(
111
                                    AbstractApiResponse::X_CORRELATION_ID
112
                                );
113
                            }
114
                        }
115 1
                        $message = $formatter->format($request, $response, $reason);
116 1
                        $logger->notice($message, $context);
117 1
                        return \GuzzleHttp\Promise\rejection_for($reason);
118 684
                    }
119
                );
120 39
            };
121 45
        };
122
    }
123
124 77
    public function addHandler($handler)
125
    {
126 77
        $this->client->getConfig('handler')->push($handler);
127 77
    }
128
129
    /**
130
     * @param RequestInterface $request
131
     * @param array $clientOptions
132
     * @return ResponseInterface
133
     * @throws ApiException
134
     * @throws \Commercetools\Core\Error\ApiException
135
     * @throws \Commercetools\Core\Error\BadGatewayException
136
     * @throws \Commercetools\Core\Error\ConcurrentModificationException
137
     * @throws \Commercetools\Core\Error\ErrorResponseException
138
     * @throws \Commercetools\Core\Error\GatewayTimeoutException
139
     * @throws \Commercetools\Core\Error\InternalServerErrorException
140
     * @throws \Commercetools\Core\Error\InvalidTokenException
141
     * @throws \Commercetools\Core\Error\NotFoundException
142
     * @throws \Commercetools\Core\Error\ServiceUnavailableException
143
     */
144 730
    public function execute(RequestInterface $request, array $clientOptions = [])
145
    {
146
        try {
147 730
            $response = $this->client->send($request, $clientOptions);
148 92
        } catch (RequestException $exception) {
149 92
            $response = $exception->getResponse();
150 92
            throw ApiException::create($request, $response, $exception);
151
        }
152
153 714
        return $response;
154
    }
155
156
    /**
157
     * @param RequestInterface[] $requests
158
     * @param array $clientOptions
159
     * @return ResponseInterface[]
160
     */
161 594
    public function executeBatch(array $requests, array $clientOptions = [])
162
    {
163 594
        $results = Pool::batch(
164 594
            $this->client,
165 594
            $requests,
166
            [
167 594
                'concurrency' => $this->concurrency,
168 594
                'options' => $clientOptions
169
            ]
170
        );
171
172 594
        $responses = [];
173 594
        foreach ($results as $key => $result) {
174 594
            $httpResponse = $result;
175 594
            if ($result instanceof RequestException) {
176 9
                $request = $requests[$key];
177 9
                $httpResponse = $result->getResponse();
178 9
                $httpResponse = ApiException::create($request, $httpResponse, $result);
179
            }
180 594
            $responses[$key] = $httpResponse;
181
        }
182
183 594
        return $responses;
184
    }
185
186
    /**
187
     * @param $oauthUri
188
     * @param $clientId
189
     * @param $clientSecret
190
     * @param $formParams
191
     * @return ResponseInterface
192
     */
193 46
    public function authenticate($oauthUri, $clientId, $clientSecret, $formParams)
194
    {
195
        $options = [
196 46
            'form_params' => $formParams,
197 46
            'auth' => [$clientId, $clientSecret]
198
        ];
199
200
        try {
201 46
            $response = $this->client->post($oauthUri, $options);
202 3
        } catch (RequestException $exception) {
203 3
            throw ApiException::create($exception->getRequest(), $exception->getResponse(), $exception);
204
        }
205 45
        return $response;
206
    }
207
208
    /**
209
     * @param RequestInterface $request
210
     * @param array $clientOptions
211
     * @return AdapterPromiseInterface
212
     */
213 4
    public function executeAsync(RequestInterface $request, array $clientOptions = [])
214
    {
215 4
        $guzzlePromise = $this->client->sendAsync($request, $clientOptions);
216
217 4
        return new Guzzle6Promise($guzzlePromise);
218
    }
219
220 78
    public static function getAdapterInfo()
221
    {
222 78
        return 'GuzzleHttp/' . Client::VERSION;
223
    }
224
225
    /**
226
     * @inheritdoc
227
     */
228 2
    public function getConfig($option)
229
    {
230 2
        return $this->client->getConfig($option);
231
    }
232
}
233