Completed
Push — master ( 44676f...b7bc18 )
by Jens
13:18
created

Guzzle5Adapter::__construct()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 0
cts 27
cp 0
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 19
nc 8
nop 1
crap 20
1
<?php
2
/**
3
 * @author @jayS-de <[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\Helper\Subscriber\CorrelationIdSubscriber;
11
use Commercetools\Core\Helper\Subscriber\TokenSubscriber;
12
use GuzzleHttp\Client;
13
use GuzzleHttp\Exception\RequestException;
14
use GuzzleHttp\Pool;
15
use GuzzleHttp\Psr7\Request;
16
use GuzzleHttp\Psr7\Response;
17
use Psr\Http\Message\RequestInterface;
18
use Psr\Http\Message\ResponseInterface;
19
use Psr\Log\LoggerInterface;
20
use Commercetools\Core\Helper\Subscriber\Log\LogSubscriber;
21
use Commercetools\Core\Error\ApiException;
22
use Psr\Log\LogLevel;
23
24
class Guzzle5Adapter implements AdapterOptionInterface, CorrelationIdAware, TokenProviderAware
25
{
26
    const DEFAULT_CONCURRENCY = 25;
27
28
    /**
29
     * @var Client
30
     */
31
    protected $client;
32
33
    /**
34
     * @var LoggerInterface
35
     */
36
    protected $logger;
37
38
    private $concurrency;
39
40
    /**
41
     * @param array $options
42
     */
43
    public function __construct(array $options = [])
44
    {
45
        if (isset($options['base_uri'])) {
46
            $options['base_url'] = $options['base_uri'];
47
            unset($options['base_uri']);
48
        }
49
        if (isset($options['concurrency'])) {
50
            $options['pool_size'] = $options['concurrency'];
51
            unset($options['concurrency']);
52
        }
53
        if (isset($options['headers'])) {
54
            $options['defaults']['headers'] = $options['headers'];
55
            unset($options['headers']);
56
        }
57
        $options = array_merge(
58
            [
59
                'allow_redirects' => false,
60
                'verify' => true,
61
                'timeout' => 60,
62
                'connect_timeout' => 10,
63
                'pool_size' => self::DEFAULT_CONCURRENCY
64
            ],
65
            $options
66
        );
67
        $this->concurrency = $options['pool_size'];
68
69
        $this->client = new Client($options);
70
    }
71
72
    public function setLogger(LoggerInterface $logger, $logLevel = LogLevel::INFO, $formatter = null)
73
    {
74
        $this->logger = $logger;
75
        if ($logger instanceof LoggerInterface) {
76
            $this->getEmitter()->attach(new LogSubscriber($logger, $formatter, $logLevel));
77
        }
78
    }
79
80
    public function addHandler($handler)
81
    {
82
        $this->getEmitter()->attach($handler);
83
    }
84
85
    public function setCorrelationIdProvider(CorrelationIdProvider $provider)
86
    {
87
        $this->addHandler(new CorrelationIdSubscriber($provider));
88
    }
89
90
    public function setOAuthTokenProvider(TokenProvider $tokenProvider)
91
    {
92
        $this->addHandler(new TokenSubscriber($tokenProvider));
93
    }
94
95
    /**
96
     * @internal
97
     * @return \GuzzleHttp\Event\Emitter|\GuzzleHttp\Event\EmitterInterface
98
     */
99
    public function getEmitter()
100
    {
101
        return $this->client->getEmitter();
102
    }
103
104
    /**
105
     * @param RequestInterface $request
106
     * @param array $clientOptions
107
     * @return ResponseInterface
108
     * @throws \Commercetools\Core\Error\ApiException
109
     * @throws \Commercetools\Core\Error\BadGatewayException
110
     * @throws \Commercetools\Core\Error\ConcurrentModificationException
111
     * @throws \Commercetools\Core\Error\ErrorResponseException
112
     * @throws \Commercetools\Core\Error\GatewayTimeoutException
113
     * @throws \Commercetools\Core\Error\InternalServerErrorException
114
     * @throws \Commercetools\Core\Error\InvalidTokenException
115
     * @throws \Commercetools\Core\Error\NotFoundException
116
     * @throws \Commercetools\Core\Error\ServiceUnavailableException
117
     */
118
    public function execute(RequestInterface $request, array $clientOptions = [])
119
    {
120
        $options = [
121
            'headers' => $request->getHeaders(),
122
            'body' => (string)$request->getBody()
123
        ];
124
        if (count($clientOptions)) {
125
            $options = array_merge($options, $clientOptions);
126
        }
127
128
        try {
129
            $guzzleRequest = $this->client->createRequest($request->getMethod(), (string)$request->getUri(), $options);
130
            $guzzleResponse = $this->client->send($guzzleRequest);
131
            $response = $this->packResponse($guzzleResponse);
132
        } catch (RequestException $exception) {
133
            $response = $this->packResponse($exception->getResponse());
134
            throw ApiException::create($request, $response, $exception);
135
        }
136
137
        return $response;
138
    }
139
140
    protected function packResponse(\GuzzleHttp\Message\ResponseInterface $response = null)
141
    {
142
        if (!$response instanceof \GuzzleHttp\Message\ResponseInterface) {
143
            return null;
144
        }
145
        return new Response(
146
            $response->getStatusCode(),
147
            $response->getHeaders(),
148
            (string)$response->getBody()
149
        );
150
    }
151
152
    /**
153
     * @param RequestInterface[] $requests
154
     * @param array $clientOptions
155
     * @return \Psr\Http\Message\ResponseInterface[]
156
     * @throws \Commercetools\Core\Error\ApiException
157
     * @throws \Commercetools\Core\Error\BadGatewayException
158
     * @throws \Commercetools\Core\Error\ConcurrentModificationException
159
     * @throws \Commercetools\Core\Error\ErrorResponseException
160
     * @throws \Commercetools\Core\Error\GatewayTimeoutException
161
     * @throws \Commercetools\Core\Error\InternalServerErrorException
162
     * @throws \Commercetools\Core\Error\InvalidTokenException
163
     * @throws \Commercetools\Core\Error\NotFoundException
164
     * @throws \Commercetools\Core\Error\ServiceUnavailableException
165
     */
166
    public function executeBatch(array $requests, array $clientOptions = [])
167
    {
168
        $results = Pool::batch(
169
            $this->client,
170
            $this->getBatchHttpRequests($requests, $clientOptions),
171
            ['pool_size' => $this->concurrency]
172
        );
173
174
        $responses = [];
175
        foreach ($results as $key => $result) {
176
            if (!$result instanceof RequestException) {
177
                $response = $this->packResponse($result);
178 View Code Duplication
            } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
179
                $httpResponse = $this->packResponse($result->getResponse());
180
                $request = $requests[$key];
181
                $response = ApiException::create($request, $httpResponse, $result);
182
            }
183
            $responses[$key] = $response;
184
        }
185
186
        return $responses;
187
    }
188
189
    /**
190
     * @param array $requests
191
     * @param array $clientOptions
192
     * @return array
193
     */
194
    protected function getBatchHttpRequests(array $requests, array $clientOptions = [])
195
    {
196
        $requests = array_map(
197
            function ($request) use ($clientOptions) {
198
                $options = ['headers' => $request->getHeaders()];
199
                if (count($clientOptions)) {
200
                    $options = array_merge($options, $clientOptions);
201
                }
202
203
                /**
204
                 * @var RequestInterface $request
205
                 */
206
                return $this->client->createRequest(
207
                    $request->getMethod(),
208
                    (string)$request->getUri(),
209
                    $options
210
                );
211
            },
212
            $requests
213
        );
214
215
        return $requests;
216
    }
217
218
    /**
219
     * @param $oauthUri
220
     * @param $clientId
221
     * @param $clientSecret
222
     * @param $formParams
223
     * @return ResponseInterface
224
     */
225
    public function authenticate($oauthUri, $clientId, $clientSecret, $formParams)
226
    {
227
        $options = [
228
            'body' => $formParams,
229
            'auth' => [$clientId, $clientSecret]
230
        ];
231
232
        try {
233
            $response = $this->client->post($oauthUri, $options);
234
        } catch (RequestException $exception) {
235
            $authRequest = $exception->getRequest();
236
            $request = new Request(
237
                $authRequest->getMethod(),
238
                $authRequest->getUrl(),
239
                $authRequest->getHeaders(),
240
                (string)$authRequest->getBody()
241
            );
242
            $response = $this->packResponse($exception->getResponse());
243
            throw ApiException::create($request, $response, $exception);
244
        }
245
        return $response;
246
    }
247
248
    /**
249
     * @param RequestInterface $request
250
     * @param array $clientOptions
251
     * @return AdapterPromiseInterface
252
     */
253
    public function executeAsync(RequestInterface $request, array $clientOptions = [])
254
    {
255
        $options = [
256
            'future' => true,
257
            'exceptions' => false,
258
            'headers' => $request->getHeaders()
259
        ];
260
        if (count($clientOptions)) {
261
            $options = array_merge($options, $clientOptions);
262
        }
263
        $request = $this->client->createRequest($request->getMethod(), (string)$request->getUri(), $options);
264
        $guzzlePromise = $this->client->send($request, $options);
265
266
        $promise = new Guzzle5Promise($guzzlePromise);
267
        $promise->then(
268
            function (\GuzzleHttp\Message\ResponseInterface $response) {
269
                return new Response(
270
                    $response->getStatusCode(),
271
                    $response->getHeaders(),
272
                    (string)$response->getBody(),
273
                    $response->getProtocolVersion(),
274
                    $response->getReasonPhrase()
275
                );
276
            }
277
        );
278
279
        return $promise;
280
    }
281
282
    public static function getAdapterInfo()
283
    {
284
        return 'GuzzleHttp/' . Client::VERSION;
285
    }
286
}
287