GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#9)
by Evgeny
02:04
created

AbstractList::getResponses()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 21
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 21
rs 8.7624
cc 6
eloc 15
nc 12
nop 0
1
<?php
2
3
namespace SimaLand\API;
4
5
use GuzzleHttp\Psr7\Response;
6
use SimaLand\API\Rest\Client;
7
use SimaLand\API\Rest\Request;
8
9
/**
10
 * Абстрактный класс для загрузки данных сущности.
11
 *
12
 * Класс реализует интерфейс Iterator.
13
 */
14
abstract class AbstractList extends Object implements \Iterator
15
{
16
    /**
17
     * Кол-во потоков.
18
     *
19
     * @var int
20
     */
21
    public $countThreads = 5;
22
23
    /**
24
     * GET параметр отвечающий за поток.
25
     *
26
     * @var string
27
     */
28
    public $keyThreads = 'page';
29
30
    /**
31
     * Ключ альтернативной пагинации.
32
     *
33
     * @var string
34
     */
35
    public $keyAlternativePagination = 'id-greater-than';
36
37
    /**
38
     * GET параметры запроса.
39
     *
40
     * @var array
41
     */
42
    public $getParams = [];
43
44
    /**
45
     * Кол-во повторов обращение к ресурсу при ошибках.
46
     *
47
     * @var int
48
     */
49
    public $repeatTimeout = 30;
50
51
    /**
52
     * Время в секундак до следующего обращения к ресурсу.
53
     *
54
     * @var int
55
     */
56
    public $repeatCount = 30;
57
58
59
    /**
60
     * SimaLand кдиент для запросов.
61
     *
62
     * @var \SimaLand\API\Rest\Client
63
     */
64
    private $client;
65
66
    /**
67
     * Список запросов.
68
     *
69
     * @var Request[]
70
     */
71
    private $requests = [];
72
73
    /**
74
     * Список данных полученные по API.
75
     *
76
     * @var array
77
     */
78
    private $values = [];
79
80
    /**
81
     * Ключ текущей записи.
82
     *
83
     * @var int
84
     */
85
    private $key;
86
87
    /**
88
     * Текущая запись.
89
     *
90
     * @var mixed
91
     */
92
    private $current;
93
94
    /**
95
     * @param Client $client
96
     * @param array $options
97
     */
98
    public function __construct(Client $client, array $options = [])
99
    {
100
        $this->client = $client;
101
        parent::__construct($options);
102
    }
103
104
    /**
105
     * Получить наименование сущности.
106
     *
107
     * @return string
108
     */
109
    abstract public function getEntity();
110
111
    /**
112
     * Добавить get параметры.
113
     *
114
     * @param array $params
115
     * @return AbstractList
116
     */
117
    public function addGetParams(array $params)
118
    {
119
        $this->getParams = array_merge($this->getParams, $params);
120
        return $this;
121
    }
122
123
    /**
124
     * Назначить следующию страницу запросу.
125
     *
126
     * @param Request $request
127
     * @param Record|null $record
128
     */
129
    public function assignPage(Request &$request, Record $record = null)
130
    {
131
        $currentPage = 1;
132
        if (!is_array($request->getParams)) {
133
            $request->getParams = (array)$request->getParams;
134
        }
135
        if (isset($request->getParams[$this->keyThreads])) {
136
            $currentPage = (int)$request->getParams[$this->keyThreads];
137
        }
138
        $request->getParams[$this->keyThreads] = $currentPage + $this->countThreads;
139
    }
140
141
    /**
142
     * Назначить номер потока для запроса.
143
     *
144
     * @param Request $request
145
     * @param int $number
146
     */
147
    public function assignThreadsNumber(Request &$request, $number = 0)
148
    {
149
        if (!is_array($request->getParams)) {
150
            $request->getParams = (array)$request->getParams;
151
        }
152
        if (!isset($request->getParams[$this->keyThreads])) {
153
            $request->getParams[$this->keyThreads] = 1;
154
        }
155
        $request->getParams[$this->keyThreads] += $number;
156
    }
157
158
    /**
159
     * Наименование ключа содержащего набора данных сущности.
160
     *
161
     * @return string
162
     */
163
    public function getCollectionKey()
164
    {
165
        return 'items';
166
    }
167
168
    /**
169
     * Наименование ключа содержащего мета данные.
170
     *
171
     * @return string
172
     */
173
    public function getMetaKey()
174
    {
175
        return '_meta';
176
    }
177
178
    /**
179
     * Палучить набор данных сущности.
180
     *
181
     * @return Response[]
182
     * @throws \Exception
183
     */
184
    public function get()
185
    {
186
        return $this->client->batchQuery($this->getRequests());
187
    }
188
189
    /**
190
     * Установить запросы к API.
191
     *
192
     * @param Request[] $requests
193
     * @throws \Exception
194
     */
195
    public function setRequests(array $requests)
196
    {
197
        $this->requests = [];
198
        foreach ($requests as $request) {
199
            if (!$request instanceof Request) {
200
                throw new \Exception('Request must be implement "\SimaLand\API\Rest\Request"');
201
            }
202
            $this->requests[] = $request;
203
        }
204
    }
205
206
    /**
207
     * Получить запросы к API.
208
     *
209
     * @return array|Rest\Request[]
210
     */
211
    public function getRequests()
212
    {
213
        if (empty($this->requests)) {
214
            $requests = [];
215
            if (!is_null($this->keyThreads) && $this->countThreads > 1) {
216
                for ($i = 0; $i < $this->countThreads; $i++) {
217
                    $requests[$i] = new Request([
218
                        'entity' => $this->getEntity(),
219
                        'getParams' => $this->getParams,
220
                    ]);
221
                    $this->assignThreadsNumber($requests[$i], $i);
222
                }
223
            } else {
224
                $requests[] = new Request([
225
                    'entity' => $this->getEntity(),
226
                    'getParams' => $this->getParams,
227
                ]);
228
            }
229
            $this->requests = $requests;
230
        }
231
        return $this->requests;
232
    }
233
234
    /**
235
     * @inheritdoc
236
     */
237
    public function current()
238
    {
239
        return $this->current;
240
    }
241
242
    /**
243
     * @inheritdoc
244
     */
245
    public function next()
246
    {
247
        if (empty($this->values)) {
248
            $this->getData();
249
        }
250
        $this->current = array_shift($this->values);
251
    }
252
253
    /**
254
     * @inheritdoc
255
     */
256
    public function key()
257
    {
258
        return $this->key++;
259
    }
260
261
    /**
262
     * @inheritdoc
263
     */
264
    public function valid()
265
    {
266
        return !empty($this->current);
267
    }
268
269
    /**
270
     * @inheritdoc
271
     */
272
    public function rewind()
273
    {
274
        $this->values = [];
275
        $this->current = null;
276
        $this->key = 0;
277
        $this->next();
278
    }
279
280
    /**
281
     * Обработка ответов от API.
282
     *
283
     * @param Response[] $responses
284
     * @return \Exception|null
285
     */
286
    private function processingResponses(array $responses)
287
    {
288
        foreach ($responses as $response) {
289
            $statusCode = $response->getStatusCode();
290
            if (($statusCode < 200 || $statusCode >= 300) && $statusCode != 404) {
291
                $body = json_decode($response->getBody(), true);
292
                $message = isset($body['message']) ? $body['message'] : $response->getReasonPhrase();
293
                return new \Exception($message, $statusCode);
294
            }
295
        }
296
        return null;
297
    }
298
299
    /**
300
     * Получение ответов от API
301
     *
302
     * @return \GuzzleHttp\Psr7\Response[]
303
     * @throws \Exception
304
     */
305
    private function getResponses()
306
    {
307
        $i = 0;
308
        $responses = [];
309
        do {
310
            if ($i > 0) {
311
                sleep($this->repeatTimeout);
312
            }
313
            try {
314
                $responses = $this->get();
315
                $e = $this->processingResponses($responses);
316
            } catch (\GuzzleHttp\Exception\RequestException $e) {
317
                // Игнорируем ошибку ответа сервера.
318
            }
319
            $i++;
320
        } while ($i <= $this->repeatCount && !is_null($e));
321
        if ($e) {
322
            throw new \Exception($e->getMessage(), $e->getCode(), $e);
323
        }
324
        return $responses;
325
    }
326
327
    /**
328
     * Получить тело ответа от API.
329
     *
330
     * @param Response $response
331
     * @return bool
332
     * @throws \Exception
333
     */
334
    private function getBody(Response $response)
335
    {
336
        $body = json_decode($response->getBody(), true);
337
        if (
338
            !$body ||
339
            ($body && !isset($body[$this->getCollectionKey()]))
340
        ) {
341
            return false;
342
        }
343
        return $body;
344
    }
345
346
    /**
347
     * Получить набор данных от API.
348
     *
349
     * @throws \Exception
350
     */
351
    private function getData()
352
    {
353
        $responses = $this->getResponses();
354
        $collectionKey = $this->getCollectionKey();
355
        $metaKey = $this->getMetaKey();
356
        $requests = $this->getRequests();
357
        $record = null;
358
        foreach ($responses as $key => $response) {
359
            $body = $this->getBody($response);
360
            if (!$body) {
361
                unset($requests[$key]);
362
                continue;
363
            }
364
            foreach ($body[$collectionKey] as $item) {
365
                $record = new Record([
366
                    'data' => $item,
367
                    'meta' => isset($body[$metaKey]) ? $body[$metaKey] : null,
368
                ]);
369
                $this->values[] = $record;
370
            }
371
            if (!is_null($record)) {
372
                $this->assignPage($requests[$key], $record);
373
            }
374
        }
375
        $this->setRequests($requests);
376
    }
377
}
378