Completed
Push — master ( a46561...dc2809 )
by Dmitry
02:55
created

JsonTransport::getLogger()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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