Completed
Push — master ( 735ffd...9b092c )
by Anton
8s
created

ContentClient::sendRequest()   C

Complexity

Conditions 8
Paths 10

Size

Total Lines 35
Code Lines 21

Duplication

Lines 35
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 35
loc 35
ccs 0
cts 22
cp 0
rs 5.3846
cc 8
eloc 21
nc 10
nop 3
crap 72
1
<?php
2
/**
3
 * Yandex PHP Library
4
 *
5
 * @copyright NIX Solutions Ltd.
6
 * @link      https://github.com/nixsolutions/yandex-php-library
7
 */
8
9
/**
10
 * @namespace
11
 */
12
namespace Yandex\Market\Content;
13
14
use GuzzleHttp\Client;
15
use GuzzleHttp\ClientInterface;
16
use Psr\Http\Message\UriInterface;
17
use Yandex\Common\AbstractServiceClient;
18
use GuzzleHttp\Psr7\Response;
19
use GuzzleHttp\Exception\ClientException;
20
use Yandex\Common\Exception\ForbiddenException;
21
use Yandex\Common\Exception\UnauthorizedException;
22
use Yandex\Market\Content\Exception\ContentRequestException;
23
use Yandex\Market\Content\Models;
24
25
/**
26
 * Class ContentClient
27
 *
28
 * @category Yandex
29
 * @package  MarketContent
30
 *
31
 * @author  Oleg Scherbakov <[email protected]>
32
 * @created 27.12.15 19:50
33
 */
34
class ContentClient extends AbstractServiceClient
35
{
36
    /**
37
     * Requested version of API
38
     *
39
     * @var string
40
     */
41
    private $version = 'v1';
42
43
    /**
44
     * API domain
45
     *
46
     * @var string
47
     */
48
    protected $serviceDomain = 'api.content.market.yandex.ru';
49
50
    /**
51
     * Store limits information during each API request
52
     *
53
     * @var array
54
     */
55
    private $limits = array();
56
57
    /**
58
     * Get url to service resource with parameters
59
     *
60
     * @param  string $resource
61
     * @see    http://api.yandex.ru/market/partner/doc/dg/concepts/method-call.xml
62
     * @return string
63
     */
64 29
    public function getServiceUrl($resource = '')
65
    {
66 29
        return $this->serviceScheme . '://' . $this->serviceDomain . '/'
67 29
        . $this->version . '/' . $resource;
68
    }
69
70
    /**
71
     * @param string $token access token
72
     */
73 29
    public function __construct($token = '')
74
    {
75 29
        $this->setAccessToken($token);
76 29
    }
77
78
    /**
79
     * @return ClientInterface
80
     */
81 View Code Duplication
    protected function getClient()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
82
    {
83
        if (is_null($this->client)) {
84
            $defaultOptions = [
85
                'base_uri' => $this->getServiceUrl(),
86
                'headers' => [
87
                    'Host' => $this->getServiceDomain(),
88
                    'Accept' => '*/*',
89
                    'Authorization' => $this->getAccessToken(),
90
                ]
91
            ];
92
            if ($this->getProxy()) {
93
                $defaultOptions['proxy'] = $this->getProxy();
94
            }
95
            if ($this->getDebug()) {
96
                $defaultOptions['debug'] = $this->getDebug();
97
            }
98
            $this->client = new Client($defaultOptions);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \GuzzleHttp\Client($defaultOptions) of type object<GuzzleHttp\Client> is incompatible with the declared type null of property $client.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
99
        }
100
101
        return $this->client;
102
    }
103
104
    /**
105
     * Sends a request
106
     *
107
     * @param string              $method  HTTP method
108
     * @param string|UriInterface $uri     URI object or string.
109
     * @param array               $options Request options to apply.
110
     *
111
     * @return Response
112
     *
113
     * @throws ForbiddenException
114
     * @throws UnauthorizedException
115
     * @throws ContentRequestException
116
     */
117 View Code Duplication
    protected function sendRequest($method, $uri, array $options = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
118
    {
119
        try {
120
            $response = $this->getClient()->request($method, $uri, $options);
0 ignored issues
show
Bug introduced by
It seems like $uri defined by parameter $uri on line 117 can also be of type object<Psr\Http\Message\UriInterface>; however, GuzzleHttp\Client::request() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
121
        } catch (ClientException $ex) {
122
            $result = $ex->getResponse();
123
            $code = $result->getStatusCode();
124
            $message = $result->getReasonPhrase();
125
126
            $body = $result->getBody();
127
            if ($body) {
128
                $jsonBody = json_decode($body);
129
                if ($jsonBody && isset($jsonBody->error) && isset($jsonBody->error->message)) {
130
                    $message = $jsonBody->error->message;
131
                }
132
            }
133
134
            if ($code === 403) {
135
                throw new ForbiddenException($message);
136
            }
137
138
            if ($code === 401) {
139
                throw new UnauthorizedException($message);
140
            }
141
142
            throw new ContentRequestException(
143
                'Service responded with error code: "' . $code . '" and message: "' . $message . '"',
144
                $code
145
            );
146
        }
147
        // @note: Finally? php >= 5.5
148
        $this->setLimits($response->getHeaders());
149
150
        return $response;
151
    }
152
153
    private function setLimits($headers)
154
    {
155
        // const as header name?
156
        $limitHeaders = [
157
            'X-RateLimit-Daily-Limit',
158
            'X-RateLimit-Daily-Remaining',
159
            'X-RateLimit-Global-Limit',
160
            'X-RateLimit-Global-Remaining',
161
            'X-RateLimit-Method-Limit',
162
            'X-RateLimit-Method-Remaining',
163
            'X-RateLimit-Until'
164
        ];
165
166
        $this->limits = array();
167
168
        foreach ($headers as $key => $value) {
169
            if (in_array($key, $limitHeaders, true)) {
170
                $this->limits[$key] = (int) $value[0];
171
            }
172
        }
173
    }
174
175
    /**
176
     * Get information about API limits
177
     *
178
     * @return array|false
179
     */
180
    public function getLimits()
181
    {
182
        return $this->limits;
183
    }
184
185
    /**
186
     * Get information about specified API limit
187
     *
188
     * @return array|false
189
     */
190
    public function getLimit($name)
191
    {
192
        if (isset($this->limits[$name])) {
193
            return $this->limits[$name];
194
        }
195
196
        return false;
197
    }
198
199
    /**
200
     * Returns API service response.
201
     *
202
     * @param  string $resource
203
     * @return array
204
     * @throws ContentRequestException
205
     * @throws ForbiddenException
206
     * @throws UnauthorizedException
207
     */
208 29
    protected function getServiceResponse($resource)
209
    {
210 29
        $response = $this->sendRequest('GET', $this->getServiceUrl($resource));
211 29
        $decodedResponseBody = $this->getDecodedBody($response->getBody());
212
213 29
        return $decodedResponseBody;
214
    }
215
216
    /**
217
     * Returns URL-encoded query string
218
     *
219
     * @note: similar to http_build_query(),
220
     * but transform key=>value where key == value to "?key" param.
221
     *
222
     * @param array|object $queryData
223
     * @param string       $prefix
224
     * @param string       $argSeparator
225
     * @param int          $encType
226
     *
227
     * @return string $queryString
228
     */
229 25
    protected function buildQueryString($queryData, $prefix = '', $argSeparator = '&', $encType = PHP_QUERY_RFC3986)
230
    {
231 25
        foreach ($queryData as $k => &$v) {
232 22
            if (!is_scalar($v)) {
233
                $v = implode(',', $v);
234
            }
235 25
        }
236
237 25
        $queryString = http_build_query($queryData, $prefix, $argSeparator, $encType);
238
239 25
        foreach ($queryData as $k => $v) {
240 22
            if ($k==$v) {
241 1
                $queryString = str_replace("$k=$v", $v, $queryString);
242 1
            }
243 25
        }
244
245 25
        return $queryString;
246
    }
247
}
248