Completed
Push — master ( 301e7f...9db202 )
by Dmitry
03:03
created

JsonTransport   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 207
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 15

Test Coverage

Coverage 54.65%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 15
dl 0
loc 207
ccs 47
cts 86
cp 0.5465
rs 9.1666
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getServiceUrl() 0 12 3
A setHeaders() 0 4 1
A setLogger() 0 4 1
C request() 0 36 7
A getHttpClient() 0 10 2
A getLogger() 0 8 2
A getMessageFormatter() 0 7 2
A getHttpHandlers() 0 9 1
A prepareHeaders() 0 18 3
A prepareBody() 0 7 1
1
<?php
2
/**
3
 * @author Dmitry Gladyshev <[email protected]>
4
 * @date 16/08/2016 18:06
5
 */
6
7
namespace Yandex\Direct\Transport;
8
9
use GuzzleHttp\Client;
10
use GuzzleHttp\ClientInterface;
11
use GuzzleHttp\Exception\RequestException;
12
use GuzzleHttp\HandlerStack;
13
use GuzzleHttp\MessageFormatter;
14
use GuzzleHttp\Middleware;
15
use Psr\Log\LoggerAwareInterface;
16
use Psr\Log\LoggerInterface;
17
use Psr\Log\NullLogger;
18
use Yandex\Direct\ConfigurableTrait;
19
use Yandex\Direct\Exception\RuntimeException;
20
use Yandex\Direct\Exception\TransportRequestException;
21
22
/**
23
 * Class JsonTransport
24
 * @package Yandex\Direct\Transport
25
 */
26
final class JsonTransport implements TransportInterface, LoggerAwareInterface
27
{
28
    use ConfigurableTrait;
29
30
    /**
31
     * @var string
32
     */
33
    private $baseUrl = 'https://api.direct.yandex.com';
34
35
    /**
36
     * @var ClientInterface
37
     */
38
    private $httpClient;
39
40
    /**
41
     * Custom Service urls
42
     * @var array
43
     */
44
    private $serviceUrls = [];
45
46
    /**
47
     * @var array
48
     */
49
    private $headers = [
50
        'Content-Type' => 'application/json; charset=utf-8'
51
    ];
52
53
    /**
54
     * @var LoggerInterface
55
     */
56
    private $logger;
57
58
    /**
59
     * @var MessageFormatter
60
     */
61
    private $logMessageFormatter;
62
63
    /**
64
     * JsonTransport constructor.
65
     *
66
     * @param array $options
67
     */
68 34
    public function __construct(array $options = [])
69
    {
70 34
        $this->setOptions($options);
71 34
    }
72
73
    /**
74
     * @inheritdoc
75
     */
76 2
    public function getServiceUrl($serviceName)
77
    {
78 2
        if (isset($this->serviceUrls[$serviceName])) {
79
            // If service url is absolute
80 1
            if (preg_match('#http[s]*://#u', $this->serviceUrls[$serviceName])) {
81 1
                return $this->serviceUrls[$serviceName];
82
            }
83 1
            return $this->baseUrl . $this->serviceUrls[$serviceName];
84
        }
85
86 2
        return $this->baseUrl . '/json/v5/' . strtolower($serviceName);
87
    }
88
89
    /**
90
     * @param array $headers
91
     */
92
    public function setHeaders(array $headers)
93
    {
94
        $this->headers = array_merge($this->headers, $headers);
95
    }
96
97
    /**
98
     * @inheritdoc
99
     */
100
    public function setLogger(LoggerInterface $logger)
101
    {
102
        $this->logger = $logger;
103
    }
104
105
    /**
106
     * @param TransportRequestInterface $request
107
     * @return JsonTransportResponse
108
     * @throws RuntimeException
109
     * @throws TransportRequestException
110
     */
111 1
    public function request(TransportRequestInterface $request)
112
    {
113 1
        $log = $this->getLogger();
114
115
        try {
116 1
            $client = $this->getHttpClient();
117
118 1
            $httpResponse = $client->request('POST', $this->getServiceUrl($request->getService()), [
119 1
                'headers' => $this->prepareHeaders($request),
120 1
                'body' => $this->prepareBody($request)
121 1
            ]);
122
123 1
            $httpResponseHeaders = $httpResponse->getHeaders();
124
125 1
            return new JsonTransportResponse([
126 1
                'headers' => $httpResponse->getHeaders(),
127 1
                'body' => $httpResponse->getBody()->__toString(),
128 1
                'requestId' => isset($httpResponseHeaders['RequestId']) ? current($httpResponseHeaders['RequestId']) : null,
129 1
                'units' => isset($httpResponseHeaders['Units']) ? current($httpResponseHeaders['Units']) : null
130 1
            ]);
131
        } catch (RequestException $e) {
132
            $log->error("Transport error: {$e->getMessage()} [CODE: {$e->getCode()}]");
133
            throw new TransportRequestException(
134
                $e->getMessage(),
135
                $e->getCode(),
136
                $e->getRequest()->getHeaders(),
137
                $e->getRequest()->getBody()->__toString(),
138
                $e->hasResponse() ? $e->getResponse()->getHeaders() : [],
139
                $e->hasResponse() ? $e->getResponse()->getBody()->__toString() : '',
140
                $e->getPrevious()
141
            );
142
        } catch (\Exception $e) {
143
            $log->error("Runtime error: {$e->getMessage()} [CODE: {$e->getCode()}]");
144
            throw new RuntimeException($e->getMessage(), $e->getCode(), $e->getPrevious());
145
        }
146
    }
147
148
    /**
149
     * @return ClientInterface
150
     */
151 1
    private function getHttpClient()
152
    {
153 1
        if ($this->httpClient === null) {
154
            $this->httpClient = new Client([
155
                'base_uri' => $this->baseUrl,
156
                'handler' => $this->getHttpHandlers()
157
            ]);
158
        }
159 1
        return $this->httpClient;
160
    }
161
162
    /**
163
     * @return LoggerInterface
164
     */
165 1
    private function getLogger()
166
    {
167
        // Use stub if logger is not initialized
168 1
        if ($this->logger === null) {
169 1
            $this->logger = new NullLogger;
170 1
        }
171 1
        return $this->logger;
172
    }
173
174
    /**
175
     * @return MessageFormatter
176
     */
177
    private function getMessageFormatter()
178
    {
179
        if ($this->logMessageFormatter === null) {
180
            $this->logMessageFormatter = new MessageFormatter(MessageFormatter::DEBUG);
181
        }
182
        return $this->logMessageFormatter;
183
    }
184
185
    /**
186
     * @return HandlerStack
187
     */
188
    private function getHttpHandlers()
189
    {
190
        $stack = HandlerStack::create();
191
        $stack->push(Middleware::log(
192
            $this->getLogger(),
193
            $this->getMessageFormatter()
194
        ));
195
        return $stack;
196
    }
197
198
    /**
199
     * @param JsonTransportRequest | TransportRequestInterface $request
200
     * @return array
201
     */
202 1
    private function prepareHeaders(TransportRequestInterface $request)
203
    {
204 1
        $headers = array_merge([
205 1
            'Authorization' => 'Bearer ' . $request->getCredentials()->getToken(),
206 1
            'Client-Login' => $request->getCredentials()->getLogin(),
207 1
            'Accept-Language' => $request->getLanguage(),
208 1
        ], $this->headers);
209
210 1
        if ($request->getUseOperatorUnits()) {
211 1
            $headers['Use-Operator-Units'] = 'true';
212 1
        }
213
214 1
        if ($request->getService() == 'AgencyClients') {
215
            unset($headers['Client-Login']);
216
        }
217
218 1
        return $headers;
219
    }
220
221
    /**
222
     * @param JsonTransportRequest | TransportRequestInterface $request
223
     * @return string
224
     */
225 1
    private function prepareBody(TransportRequestInterface $request)
226
    {
227 1
        return json_encode(
228 1
            array_merge(['method' => $request->getMethod()], $request->getParams()),
229 1
            JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT
230 1
        );
231
    }
232
}
233