Completed
Push — master ( 37427d...780143 )
by Dmitry
02:21
created

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