Passed
Push — master ( da0795...78880b )
by Jens
14:45 queued 18s
created

Guzzle6Adapter::getConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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