Completed
Push — master ( 85a630...b97b88 )
by Dmitry
02:41
created

JsonTransport::prepareBody()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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