Completed
Push — master ( 427e7d...a0cbad )
by Dmitriy
8s
created

MetricaClient::sendRequest()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 29
Code Lines 17

Duplication

Lines 29
Ratio 100 %

Code Coverage

Tests 16
CRAP Score 5

Importance

Changes 6
Bugs 2 Features 2
Metric Value
c 6
b 2
f 2
dl 29
loc 29
ccs 16
cts 16
cp 1
rs 8.439
cc 5
eloc 17
nc 5
nop 3
crap 5
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\Metrica;
13
14
use Yandex\Common\AbstractServiceClient;
15
use Psr\Http\Message\UriInterface;
16
use GuzzleHttp\Psr7\Response;
17
use GuzzleHttp\Exception\ClientException;
18
use Yandex\Common\Exception\ForbiddenException;
19
use Yandex\Common\Exception\UnauthorizedException;
20
use Yandex\Common\Exception\TooManyRequestsException;
21
use Yandex\Metrica\Exception\MetricaException;
22
23
/**
24
 * Class MetricaClient
25
 *
26
 * @category Yandex
27
 * @package Metrica
28
 *
29
 * @author   Alexander Khaylo <[email protected]>
30
 * @created  12.02.14 15:46
31
 */
32
class MetricaClient extends AbstractServiceClient
33
{
34
    /**
35
     * API domain
36
     *
37
     * @var string
38
     */
39
    protected $serviceDomain = 'api-metrika.yandex.ru/management/v1';
40
41
    /**
42
     * @param string $token access token
43
     */
44 55
    public function __construct($token = '')
45
    {
46 55
        $this->setAccessToken($token);
47 55
    }
48
49
    /**
50
     * Get url to service resource with parameters
51
     *
52
     * @param string $resource
53
     * @param array $params
54
     * @see http://api.yandex.ru/metrika/doc/ref/concepts/method-call.xml
55
     * @return string
56
     */
57 27
    public function getServiceUrl($resource = '', $params = [])
58
    {
59 27
        $format = $resource === '' ? '' : '.json';
60 27
        $url = $this->serviceScheme . '://' . $this->serviceDomain . '/'
61 27
            . $resource . $format . '?oauth_token=' . $this->getAccessToken();
62
63 27
        if ($params) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $params of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
64 1
            $url .= '&' . http_build_query($params);
65 1
        }
66
67 27
        return $url;
68
    }
69
70
    /**
71
     * Sends a request
72
     *
73
     * @param string              $method  HTTP method
74
     * @param string|UriInterface $uri     URI object or string.
75
     * @param array               $options Request options to apply.
76
     *
77
     * @return Response
78
     *
79
     * @throws ForbiddenException
80
     * @throws UnauthorizedException
81
     * @throws MetricaException
82
     */
83 26 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...
84
    {
85
        try {
86 26
            $response = $this->getClient()->request($method, $uri, $options);
87 26
        } catch (ClientException $ex) {
88 4
            $result = $ex->getResponse();
89 4
            $code = $result->getStatusCode();
90 4
            $message = $result->getReasonPhrase();
91
92 4
            if ($code === 403) {
93 1
                throw new ForbiddenException($message);
94
            }
95
96 3
            if ($code === 401) {
97 1
                throw new UnauthorizedException($message);
98
            }
99
100 2
            if ($code === 429) {
101 1
                throw new TooManyRequestsException($message);
102
            }
103
104 1
            throw new MetricaException(
105 1
                'Service responded with error code: "' . $code . '" and message: "' . $message . '"',
106
                $code
107 1
            );
108
        }
109
110 22
        return $response;
111
    }
112
113
    /**
114
     * Send GET request to API resource
115
     *
116
     * @param string $resource
117
     * @param array $params
118
     * @return array
119
     */
120 5
    protected function sendGetRequest($resource, $params = [])
121
    {
122 5
        $response = $this->sendRequest(
123 5
            'GET',
124 5
            $this->getServiceUrl($resource, $params),
125
            [
126
                'headers' => [
127 5
                    'Accept' => 'application/x-yametrika+json',
128 5
                    'Content-Type' => 'application/x-yametrika+json',
129
                ]
130 5
            ]
131 5
        );
132
133 1
        $decodedResponseBody = $this->getDecodedBody($response->getBody());
134
135 1 View Code Duplication
        if (isset($decodedResponseBody['links']) && isset($decodedResponseBody['links']['next'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
136
            $url = $decodedResponseBody['links']['next'];
137
            unset($decodedResponseBody['rows']);
138
            unset($decodedResponseBody['links']);
139
            return $this->getNextPartOfList($url, $decodedResponseBody);
140
        }
141 1
        return $decodedResponseBody;
142
    }
143
144
    /**
145
     * Send custom GET request to API resource
146
     *
147
     * @param string $url
148
     * @param array $data
149
     * @return array
150
     */
151
    protected function getNextPartOfList($url, $data = [])
152
    {
153
        $response = $this->sendRequest(
154
            'GET',
155
            $url,
156
            [
157
                'headers' => [
158
                    'Accept' => 'application/x-yametrika+json',
159
                    'Content-Type' => 'application/x-yametrika+json',
160
                ]
161
            ]
162
        );
163
164
        $decodedResponseBody = $this->getDecodedBody($response->getBody());
165
166
        $mergedDecodedResponseBody = array_merge_recursive($data, $decodedResponseBody);
167
168 View Code Duplication
        if (isset($mergedDecodedResponseBody['links']) && isset($mergedDecodedResponseBody['links']['next'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
169
            $url = $mergedDecodedResponseBody['links'];
170
            unset($mergedDecodedResponseBody['rows']);
171
            unset($mergedDecodedResponseBody['links']);
172
            return $this->getNextPartOfList($url, $response);
0 ignored issues
show
Documentation introduced by
$response is of type object<GuzzleHttp\Psr7\Response>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
173
        }
174
175
        return $mergedDecodedResponseBody;
176
    }
177
178
    /**
179
     * Send POST request to API resource
180
     *
181
     * @param string $resource
182
     * @param array $params
183
     * @return array
184
     */
185 7 View Code Duplication
    protected function sendPostRequest($resource, $params)
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...
186
    {
187 7
        $response = $this->sendRequest(
188 7
            'POST',
189 7
            $this->getServiceUrl($resource),
190
            [
191
                'headers' => [
192 7
                    'Accept' => 'application/x-yametrika+json',
193 7
                    'Content-Type' => 'application/x-yametrika+json',
194 7
                ],
195
                'json' => $params
196 7
            ]
197 7
        );
198
199 7
        return $this->getDecodedBody($response->getBody());
200
    }
201
202
    /**
203
     * Send PUT request to API resource
204
     *
205
     * @param string $resource
206
     * @param array $params
207
     * @return array
208
     */
209 7 View Code Duplication
    protected function sendPutRequest($resource, $params)
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...
210
    {
211 7
        $response = $this->sendRequest(
212 7
            'PUT',
213 7
            $this->getServiceUrl($resource),
214
            [
215
                'headers' => [
216 7
                    'Accept' => 'application/x-yametrika+json',
217 7
                    'Content-Type' => 'application/x-yametrika+json',
218 7
                ],
219
                'json' => $params
220 7
            ]
221 7
        );
222
223 7
        return $this->getDecodedBody($response->getBody());
224
    }
225
226
    /**
227
     * Send DELETE request to API resource
228
     *
229
     * @param string $resource
230
     * @return array
231
     */
232 7 View Code Duplication
    protected function sendDeleteRequest($resource)
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...
233
    {
234 7
        $response = $this->sendRequest(
235 7
            'DELETE',
236 7
            $this->getServiceUrl($resource),
237
            [
238
                'headers' => [
239 7
                    'Accept' => 'application/x-yametrika+json',
240 7
                    'Content-Type' => 'application/x-yametrika+json',
241
                ]
242 7
            ]
243 7
        );
244
245 7
        return $this->getDecodedBody($response->getBody());
246
    }
247
}
248