Completed
Push — master ( 9db202...d3eb33 )
by Dmitry
02:11
created

JsonTransport::getRequestClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
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
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 36
    public function __construct(array $options = [])
69
    {
70 36
        $this->setOptions($options);
71 36
    }
72
73
    /**
74
     * @inheritdoc
75
     */
76
    public function getRequestClass()
77
    {
78
        return JsonTransportRequest::class;
79
    }
80
81
    /**
82
     * @inheritdoc
83
     */
84
    public function getResponseClass()
85
    {
86
        return JsonTransportResponse::class;
87
    }
88
89
    /**
90
     * @inheritdoc
91
     */
92 2
    public function getServiceUrl($serviceName)
93
    {
94 2
        if (isset($this->serviceUrls[$serviceName])) {
95
            // If service url is absolute
96 1
            if (preg_match('#http[s]*://#u', $this->serviceUrls[$serviceName])) {
97 1
                return $this->serviceUrls[$serviceName];
98
            }
99 1
            return $this->baseUrl . $this->serviceUrls[$serviceName];
100
        }
101
102 2
        return $this->baseUrl . '/json/v5/' . strtolower($serviceName);
103
    }
104
105
    /**
106
     * @param array $headers
107
     */
108
    public function setHeaders(array $headers)
109
    {
110
        $this->headers = array_merge($this->headers, $headers);
111
    }
112
113
    /**
114
     * @inheritdoc
115
     */
116
    public function setLogger(LoggerInterface $logger)
117
    {
118
        $this->logger = $logger;
119
    }
120
121
    /**
122
     * @param RequestInterface $request
123
     * @return JsonTransportResponse
124
     * @throws RuntimeException
125
     * @throws TransportRequestException
126
     */
127 1
    public function request(RequestInterface $request)
128 1
    {
129
        try {
130 1
            $client = $this->getHttpClient();
131
132 1
            $httpResponse = $client->request('POST', $this->getServiceUrl($request->getService()), [
133 1
                'headers' => $this->prepareHeaders($request),
134 1
                'body' => $this->prepareBody($request)
135 1
            ]);
136
137 1
            $httpResponseHeaders = $httpResponse->getHeaders();
138
139 1
            return new JsonTransportResponse([
140 1
                'headers' => $httpResponse->getHeaders(),
141 1
                'body' => $httpResponse->getBody()->__toString(),
142 1
                'requestId' => isset($httpResponseHeaders['RequestId']) ? current($httpResponseHeaders['RequestId']) : null,
143 1
                'units' => isset($httpResponseHeaders['Units']) ? current($httpResponseHeaders['Units']) : null
144 1
            ]);
145
        } catch (RequestException $e) {
146
            $this->getLogger()->error("Transport error: {$e->getMessage()} [CODE: {$e->getCode()}]");
147
            throw new TransportRequestException(
148
                $e->getMessage(),
149
                $e->getCode(),
150
                $e->getRequest()->getHeaders(),
151
                $e->getRequest()->getBody()->__toString(),
152
                $e->hasResponse() ? $e->getResponse()->getHeaders() : [],
153
                $e->hasResponse() ? $e->getResponse()->getBody()->__toString() : '',
154
                $e->getPrevious()
155
            );
156
        } catch (\Exception $e) {
157
            $this->getLogger()->error("Runtime error: {$e->getMessage()} [CODE: {$e->getCode()}]");
158
            throw new RuntimeException($e->getMessage(), $e->getCode(), $e->getPrevious());
159
        }
160
    }
161
162
    /**
163
     * @return ClientInterface
164
     */
165 1
    private function getHttpClient()
166
    {
167 1
        if ($this->httpClient === null) {
168
            $this->httpClient = new Client([
169
                'base_uri' => $this->baseUrl,
170
                'handler' => $this->getHttpHandlers()
171
            ]);
172
        }
173 1
        return $this->httpClient;
174
    }
175
176
    /**
177
     * @return LoggerInterface
178
     */
179
    private function getLogger()
180
    {
181
        // Use stub if logger is not initialized
182
        if ($this->logger === null) {
183
            $this->logger = new NullLogger;
184
        }
185
        return $this->logger;
186
    }
187
188
    /**
189
     * @return MessageFormatter
190
     */
191
    private function getMessageFormatter()
192
    {
193
        if ($this->logMessageFormatter === null) {
194
            $this->logMessageFormatter = new MessageFormatter(MessageFormatter::DEBUG);
195
        }
196
        return $this->logMessageFormatter;
197
    }
198
199
    /**
200
     * @return HandlerStack
201
     */
202
    private function getHttpHandlers()
203
    {
204
        $stack = HandlerStack::create();
205
        $stack->push(Middleware::log(
206
            $this->getLogger(),
207
            $this->getMessageFormatter()
208
        ));
209
        return $stack;
210
    }
211
212
    /**
213
     * @param JsonTransportRequest | RequestInterface $request
214
     * @return array
215
     */
216 1
    private function prepareHeaders(RequestInterface $request)
217
    {
218 1
        $headers = array_merge([
219 1
            'Authorization' => 'Bearer ' . $request->getCredentials()->getToken(),
220 1
            'Client-Login' => $request->getCredentials()->getLogin(),
221 1
            'Accept-Language' => $request->getLanguage(),
222 1
        ], $this->headers);
223
224 1
        if ($request->getUseOperatorUnits()) {
225 1
            $headers['Use-Operator-Units'] = 'true';
226 1
        }
227
228 1
        if ($request->getService() == 'AgencyClients') {
229
            unset($headers['Client-Login']);
230
        }
231
232 1
        return $headers;
233
    }
234
235
    /**
236
     * @param JsonTransportRequest | RequestInterface $request
237
     * @return string
238
     */
239 1
    private function prepareBody(RequestInterface $request)
240
    {
241 1
        return json_encode(
242 1
            array_merge(['method' => $request->getMethod()], $request->getParams()),
243 1
            JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT
244 1
        );
245
    }
246
}
247