Completed
Push — develop ( 958227...1304ea )
by Jens
09:00
created

Guzzle6Adapter   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 155
Duplicated Lines 3.23 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 7
dl 5
loc 155
ccs 54
cts 54
cp 1
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
A setLogger() 0 5 1
B log() 0 30 2
A addHandler() 0 4 1
A execute() 0 11 2
A executeBatch() 5 20 3
A authenticate() 0 14 2
A executeAsync() 0 6 1
A getAdapterInfo() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * @author @jayS-de <[email protected]>
4
 */
5
6
namespace Commercetools\Core\Client\Adapter;
7
8
use Commercetools\Core\Response\AbstractApiResponse;
9
use GuzzleHttp\Client;
10
use GuzzleHttp\Exception\RequestException;
11
use GuzzleHttp\MessageFormatter;
12
use GuzzleHttp\Middleware;
13
use GuzzleHttp\Pool;
14
use GuzzleHttp\Promise\PromiseInterface;
15
use Psr\Http\Message\RequestInterface;
16
use Psr\Http\Message\ResponseInterface;
17
use Psr\Log\LoggerInterface;
18
use Commercetools\Core\Error\Message;
19
use Commercetools\Core\Error\ApiException;
20
use Psr\Log\LogLevel;
21
22
class Guzzle6Adapter implements AdapterInterface
23
{
24
    /**
25
     * @var Client
26
     */
27
    protected $client;
28
29
    protected $logger;
30
31 102
    public function __construct(array $options = [])
32
    {
33 102
        $options = array_merge(
34
            [
35 102
                'allow_redirects' => false,
36
                'verify' => true,
37
                'timeout' => 60,
38
                'connect_timeout' => 10,
39
                'pool_size' => 25
40
            ],
41
            $options
42
        );
43 102
        $this->client = new Client($options);
44 102
    }
45
46 40
    public function setLogger(LoggerInterface $logger)
47
    {
48 40
        $this->logger = $logger;
49 40
        $this->addHandler(self::log($logger, new MessageFormatter()));
50 40
    }
51
52
    /**
53
     * Middleware that logs requests, responses, and errors using a message
54
     * formatter.
55
     *
56
     * @param LoggerInterface  $logger Logs messages.
57
     * @param MessageFormatter $formatter Formatter used to create message strings.
58
     * @param string           $logLevel Level at which to log requests.
59
     *
60
     * @return callable Returns a function that accepts the next handler.
61
     */
62 419
    private static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = LogLevel::INFO)
63
    {
64
        return function (callable $handler) use ($logger, $formatter, $logLevel) {
65
            return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
66 419
                return $handler($request, $options)->then(
67
                    function ($response) use ($logger, $request, $formatter, $logLevel) {
68 419
                        $message = $formatter->format($request, $response);
69 419
                        $context[AbstractApiResponse::X_CORRELATION_ID] = $response->getHeader(
0 ignored issues
show
Coding Style Comprehensibility introduced by
$context was never initialized. Although not strictly required by PHP, it is generally a good practice to add $context = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
70 419
                            AbstractApiResponse::X_CORRELATION_ID
71
                        );
72 419
                        $logger->log($logLevel, $message, $context);
73 419
                        return $response;
74 419
                    },
75 419
                    function ($reason) use ($logger, $request, $formatter) {
76
                        $response = null;
77
                        $context = [];
78
                        if ($reason instanceof RequestException) {
79
                            $response = $reason->getResponse();
80
                            $context[AbstractApiResponse::X_CORRELATION_ID] = $response->getHeader(
81
                                AbstractApiResponse::X_CORRELATION_ID
82
                            );
83
                        }
84
                        $message = $formatter->format($request, $response, $reason);
85
                        $logger->notice($message, $context);
86
                        return \GuzzleHttp\Promise\rejection_for($reason);
87 419
                    }
88
                );
89 35
            };
90 40
        };
91
    }
92
93 40
    public function addHandler($handler)
94
    {
95 40
        $this->client->getConfig('handler')->push($handler);
96 40
    }
97
98
    /**
99
     * @param RequestInterface $request
100
     * @return ResponseInterface
101
     */
102 462
    public function execute(RequestInterface $request)
103
    {
104
        try {
105 462
            $response = $this->client->send($request);
106 77
        } catch (RequestException $exception) {
107 77
            $response = $exception->getResponse();
108 77
            throw ApiException::create($request, $response, $exception);
109
        }
110
111 438
        return $response;
112
    }
113
114
    /**
115
     * @param RequestInterface[] $requests
116
     * @return ResponseInterface[]
117
     */
118 336
    public function executeBatch(array $requests)
119
    {
120 336
        $results = Pool::batch(
121 336
            $this->client,
122
            $requests
123
        );
124
125 336
        $responses = [];
126 336
        foreach ($results as $key => $result) {
127 336
            $httpResponse = $result;
128 336 View Code Duplication
            if ($result instanceof RequestException) {
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...
129 16
                $request = $requests[$key];
130 16
                $httpResponse = $result->getResponse();
131 16
                $httpResponse = ApiException::create($request, $httpResponse, $result);
132
            }
133 336
            $responses[$key] = $httpResponse;
134
        }
135
136 336
        return $responses;
137
    }
138
139
    /**
140
     * @param $oauthUri
141
     * @param $clientId
142
     * @param $clientSecret
143
     * @param $formParams
144
     * @return ResponseInterface
145
     */
146 42
    public function authenticate($oauthUri, $clientId, $clientSecret, $formParams)
147
    {
148
        $options = [
149 42
            'form_params' => $formParams,
150 42
            'auth' => [$clientId, $clientSecret]
151
        ];
152
153
        try {
154 42
            $response = $this->client->post($oauthUri, $options);
155 3
        } catch (RequestException $exception) {
156 3
            throw ApiException::create($exception->getRequest(), $exception->getResponse(), $exception);
157
        }
158 41
        return $response;
159
    }
160
161
    /**
162
     * @param RequestInterface $request
163
     * @return AdapterPromiseInterface
164
     */
165 4
    public function executeAsync(RequestInterface $request)
166
    {
167 4
        $guzzlePromise = $this->client->sendAsync($request);
168
169 4
        return new Guzzle6Promise($guzzlePromise);
170
    }
171
172 66
    public static function getAdapterInfo()
173
    {
174 66
        return 'GuzzleHttp/' . Client::VERSION;
175
    }
176
}
177