Completed
Push — master ( 1f7ab5...0b80d4 )
by Denis
05:55
created

Collection::getPages()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * Class BookCollection
4
 *
5
 * @author       Denis Shestakov <[email protected]>
6
 * @copyright    Copyright (c) 2017, Lan Publishing
7
 * @license      MIT
8
 */
9
10
namespace Lan\Ebs\Sdk\Classes;
11
12
use ArrayObject;
13
use Exception;
14
use Lan\Ebs\Sdk\Client;
15
use Lan\Ebs\Sdk\Collection\ArticleCollection;
16
use Lan\Ebs\Sdk\Collection\IssueCollection;
17
use Lan\Ebs\Sdk\Common;
18
use ReflectionClass;
19
20
/**
21
 * Абстрактный класс для всех коллекций (+ итерируемый)
22
 *
23
 * @package      Lan\Ebs
24
 * @subpackage   Sdk
25
 * @category     Classes
26
 */
27
abstract class Collection extends ArrayObject implements Common
28
{
29
    /**
30
     * Инстанс клиента API
31
     *
32
     * @var Client
33
     */
34
    private $client;
35
36
    /**
37
     * Флаг, сигнализирующий что коллекция загружена
38
     *
39
     * @var int
40
     */
41
    private $loadStatus = 0;
42
43
    /**
44
     * Имена полей, подлежаших получению через API
45
     *
46
     * @var array
47
     */
48
    private $fields = [];
49
50
    /**
51
     * Класс модели
52
     *
53
     * @var Model|string
54
     */
55
    private $class = null;
56
57
    /**
58
     * Лимит получаемых моделей коллекции через API
59
     *
60
     * @var int
61
     */
62
    private $limit = null;
63
64
    /**
65
     * Смещение выборки моделей через API
66
     *
67
     * @var int
68
     */
69
    private $offset = null;
70
71
    /**
72
     * Всего элементов без учета лимита
73
     *
74
     * @var int
75
     */
76
    private $fullCount = null;
77
78
    /**
79
     * Конструктор коллекции
80
     *
81
     * @param Client $client Инстанс клиента
82
     * @param array $fields Поля для выборки
83
     * @param string $class Класс модели
84
     * @param int $limit Лимит выборки
85
     * @param int $offset Смещение выборки
86
     *
87
     * Пример:
88
     * ```php
89
     *      $token = '7c0c2193d27108a509abd8ea84a8750c82b3a520'; // токен для тестового подписчика
90
     *
91
     *      $client = new Client($token); // инициализация клиента
92
     *
93
     *      $bookCollection = new BookCollection($client, [], '\Lan\Ebs\Sdk\Model\Book', 5, 10); // инициализация коллекции книг
94
     * ```
95
     *
96
     * @throws Exception
97
     *
98
     * @see ArticleCollection::__construct
99
     * @see BookCollection::__construct
100
     * @see IssueCollection::__construct
101
     * @see JournalCollection::__construct
102
     * @see UserCollection::__construct
103
     */
104 3
    public function __construct(Client $client, array $fields, $class, $limit, $offset)
105
    {
106 3
        if (!$client) {
107
            throw new Exception('Клиент не инициализирован');
108
        }
109
110 3
        if (!is_array($fields)) {
111
            throw new Exception('Fields for model of collection mast be array');
112
        }
113
114 3
        $reflectionClass = new ReflectionClass($class);
115
116 3
        if (!$reflectionClass->isSubclassOf(Model::class)) {
117
            throw new Exception('Class of model collection not subclass for Model');
118
        }
119
120 3
        $this->client = $client;
121 3
        $this->fields = $fields;
122 3
        $this->class = $class;
123
124 3
        $this->setLimit($limit);
125 3
        $this->setOffset($offset);
126 3
    }
127
128
    /**
129
     * Установка лимита выборки
130
     *
131
     * Установка/изменение лимита выборки коллекции. Вызывет перезагрузку коллекции если значение лимита изменилось
132
     *
133
     * @param int $limit Значение лимита выборки
134
     *
135
     * Пример:
136
     * ```php
137
     *      $token = '7c0c2193d27108a509abd8ea84a8750c82b3a520'; // токен для тестового подписчика
138
     *
139
     *      $client = new Client($token); // инициализация клиента
140
     *
141
     *      $bookCollection = new BookCollection($client, [], '\Lan\Ebs\Sdk\Model\Book', 5, 100); // инициализация коллекции книг
142
     *
143
     *      $bookCollection->setLimit(100); // изменение лимита с 5 до 100
144
     * ```
145
     *
146
     * @return $this
147
     *
148
     * Пример:
149
     * ```php
150
     *      echo $bookCollection->setLimit(100)->count(); // Выведет количество элементов коллекции
151
     * ```
152
     *
153
     * @throws Exception
154
     */
155 3 View Code Duplication
    public function setLimit($limit)
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...
156
    {
157 3
        $isChanged = $this->limit != $limit;
158
159 3
        $this->limit = $limit;
160
161 3
        if ($isChanged && $this->loadStatus == 200) {
162
            $this->load(true);
163
        }
164
165 3
        return $this;
166
    }
167
168
    /**
169
     * Загрузка коллекции
170
     *
171
     * Загрузка осуществляется только после вызова зависимого метода (ленивая загрузка)
172
     *
173
     * @param bool $force Заново загружать коллекцию даже если она загружена ранее
174
     *
175
     * Пример:
176
     * ```php
177
     *      $token = '7c0c2193d27108a509abd8ea84a8750c82b3a520'; // токен для тестового подписчика
178
     *
179
     *      $client = new Client($token); // инициализация клиента
180
     *
181
     *      $bookCollection = new BookCollection($client, [], '\Lan\Ebs\Sdk\Model\Book', 5, 100); // инициализация коллекции книг
182
     *
183
     *      // Вызова метода загрузки еще небыло.. коллекция пустая
184
     *      $bookCollection->load(); // загрузка коллекции данными
185
     *      // Запрос к API выполнен.. коллекция загружена
186
     * ```
187
     *
188
     * @return $this Вернет текущую коллекцию
189
     *
190
     * Пример:
191
     * ```php
192
     *       echo $bookCollection->load()->count(); // Выведет количество элементов коллекции
193
     * ```
194
     *
195
     * @throws Exception
196
     *
197
     * @see Collection::setLimit()
198
     * @see Collection::setOffset()
199
     * @see Collection::getFullCount()
200
     * @see Collection::getCount()
201
     * @see Collection::getData()
202
     * @see Collection::reset()
203
     * @see Collection::end()
204
     * @see CollectionIterator::rewind()
205
     */
206 3
    public function load($force = false)
207
    {
208 3
        if ($this->loadStatus == 200 && !$force) {
209 2
            return $this;
210
        }
211
212
        $params = [
213 3
            'limit' => $this->limit,
214 3
            'offset' => $this->offset
215
        ];
216
217 3
        if (!empty($this->fields)) {
218
            $params['fields'] = implode(',', (array)$this->fields);
219
        }
220
221 3
        $response = $this->client->getResponse($this->getUrl(__FUNCTION__), $params);
222
223 3
        $this->exchangeArray($response['data']);
224
225 3
        $this->loadStatus = $response['status'];
226
227 3
        $this->fullCount = $response['count'];
228
229 3
        unset($response);
230
231 3
        return $this;
232
    }
233
234
    /**
235
     * Установка смещения выборки
236
     *
237
     * Установка/изменение смещения выборки коллекции. Вызывет перезагрузку коллекции если значение смещения изменилось
238
     *
239
     * @param int $offset Значение смещения выборки
240
     *
241
     * Пример:
242
     * ```php
243
     *      $token = '7c0c2193d27108a509abd8ea84a8750c82b3a520'; // токен для тестового подписчика
244
     *
245
     *      $client = new Client($token); // инициализация клиента
246
     *
247
     *      $bookCollection = new BookCollection($client, [], '\Lan\Ebs\Sdk\Model\Book', 5, 100); // инициализация коллекции книг
248
     *
249
     *      $bookCollection->setOffset(1000); // изменение смещения со 100 до 1000
250
     * ```
251
     *
252
     * @return $this Вернет текущую коллекцию
253
     *
254
     * Пример:
255
     * ```php
256
     *      echo $bookCollection->setOffset(1000)->count(); // Выведет количество элементов коллекции
257
     * ```
258
     *
259
     * @throws Exception
260
     */
261 3 View Code Duplication
    public function setOffset($offset)
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...
262
    {
263 3
        $isChanged = $this->offset != $offset;
264
265 3
        $this->offset = $offset;
266
267 3
        if ($isChanged && $this->loadStatus == 200) {
268
            $this->load(true);
269
        }
270
271 3
        return $this;
272
    }
273
274
    /**
275
     * Получение количества всех элементов без учета лимита
276
     *
277
     * Вернет общее количество элементов необходимое, например, для вычисления постраничной выборки
278
     *
279
     * Пример:
280
     * ```php
281
     *      $token = '7c0c2193d27108a509abd8ea84a8750c82b3a520'; // токен для тестового подписчика
282
     *
283
     *      $client = new Client($token); // инициализация клиента
284
     *
285
     *      $bookCollection = new BookCollection($client, [], '\Lan\Ebs\Sdk\Model\Book', 5, 100); // инициализация коллекции книг
286
     *
287
     *      echo $bookCollection->getFullCount(); // Вернет количество элементов без учета лимита
288
     * ```
289
     *
290
     * @return int
291
     *
292
     * Пример:
293
     * ```php
294
     *      echo $bookCollection>getFullCount(); // Вернет, например, 286
295
     *      echo $bookCollection->сount(); // Вернет, например, 5
296
     *      // Итого получаем ceil($bookCollection>getFullCount() /  $bookCollection>getLimit()) = 58 страниц
297
     * ```
298
     *
299
     * @throws Exception
300
     */
301
    public function getFullCount()
302
    {
303
        $this->load();
304
305
        return $this->fullCount;
306
    }
307
308
    /**
309
     * Получение нового инстанса итератора коллекции
310
     *
311
     * Итератор для реализации итерируемой коллекции
312
     *
313
     * @return CollectionIterator Вернет экзепляря итератора текущей коллекции
314
     */
315 1
    public function getIterator()
316
    {
317 1
        return new CollectionIterator($this);
318
    }
319
320
    /**
321
     * Количество моделей в коллекции
322
     *
323
     * Фактическое число моделей в коллекции
324
     *
325
     * Пример:
326
     * ```php
327
     *      $token = '7c0c2193d27108a509abd8ea84a8750c82b3a520'; // токен для тестового подписчика
328
     *
329
     *      $client = new Client($token); // инициализация клиента
330
     *
331
     *      $bookCollection = new BookCollection($client, [], '\Lan\Ebs\Sdk\Model\Book', 5, 100); // инициализация коллекции книг
332
     *
333
     *      echo $bookCollection>getFullCount(); // Вернет количество элементов без учета лимита
334
     * ```
335
     *
336
     * @return int
337
     *
338
     * Пример:
339
     * ```php
340
     *      echo $bookCollection->сount(); // Вернет, например, 5 (но не больше 5 - фактическое количество)
341
     * ```
342
     *
343
     * @throws Exception
344
     */
345 2
    public function count()
346
    {
347 2
        $this->load();
348
349 2
        return parent::count();
350
    }
351
352
    /**
353
     * Получение коллекции в виде массива
354
     *
355
     * Выгрузка коллекции в массив
356
     *
357
     * Пример:
358
     * ```php
359
     *      $token = '7c0c2193d27108a509abd8ea84a8750c82b3a520'; // токен для тестового подписчика
360
     *
361
     *      $client = new Client($token); // инициализация клиента
362
     *
363
     *      $bookCollection = new BookCollection($client, [], '\Lan\Ebs\Sdk\Model\Book', 1, 10); // инициализация коллекции книг
364
     *
365
     *      print_r($bookCollection->getData()); // Вернет количество элементов без учета лимита
366
     * ```
367
     *
368
     * @return array
369
     *
370
     * Пример:
371
     * ```
372
     * [
373
     *      'id' => 22445,
374
     *      'name' => 'Свадьба. Сцена в одном действии',
375
     *      'authors' => 'Чехов А.П.'
376
     * ]
377
     * ```
378
     *
379
     * @throws Exception
380
     */
381 1
    public function getData()
382
    {
383 1
        $this->load();
384
385 1
        return $this->getArrayCopy();
386
    }
387
388
    /**
389
     * Получение первой модели в коллекции
390
     *
391
     * Вернет первую модель коллекции.
392
     *
393
     * @return Model
394
     *
395
     * @throws Exception
396
     */
397 3
    public function reset()
398
    {
399 3
        $this->load();
400
401 3
        return $this->createModel(reset($this));
402
    }
403
404
    /**
405
     * Создание модели по переданным данным
406
     *
407
     * Создает модель по ее данным
408
     *
409
     * Пример:
410
     * ```php
411
     *      $token = '7c0c2193d27108a509abd8ea84a8750c82b3a520'; // токен для тестового подписчика
412
     *
413
     *      $client = new Client($token); // инициализация клиента
414
     *
415
     *      $bookCollection = new BookCollection($client, [], '\Lan\Ebs\Sdk\Model\Book', 1, 10); // инициализация коллекции книг
416
     *
417
     *      $bookData = [
418
     *          'id' => 22445,
419
     *          'name' => 'Свадьба. Сцена в одном действии',
420
     *          'authors' => 'Чехов А.П.'
421
     *      ];
422
     *
423
     *      $book = $bookCollection->createModel($bookData);
424
     * ```
425
     *
426
     * @param array $data Данные для создания модели
427
     *
428
     * @return Model Вернет модель на основе данных
429
     *
430
     * @throws Exception
431
     */
432 3
    public function createModel(array $data = null)
433
    {
434 3
        $class = $this->class;
435
436
        /**
437
         * @var Model $model
438
         */
439 3
        $model = new $class($this->client, $this->fields);
440
441 3
        $model->set($data === null ? current($this) : $data);
442
443 3
        return $model;
444
    }
445
446
    /**
447
     * Получение последней модели в коллекции
448
     *
449
     * Вернет полделнюю модель коллекции.
450
     *
451
     * @return Model
452
     *
453
     * @throws Exception
454
     */
455 2
    public function end()
456
    {
457 2
        $this->load();
458
459 2
        return $this->createModel(end($this));
460
    }
461
462
    /**
463
     * Получение инстанса клиента
464
     *
465
     * @return Client
466
     */
467
    protected function getClient()
468
    {
469
        return $this->client;
470
    }
471
472
    /**
473
     * Получение текущего лимита коллекции
474
     *
475
     * @return int
476
     */
477
    public function getLimit()
478
    {
479
        return $this->limit;
480
    }
481
482
    /**
483
     *
484
     * Получение текущего смещения коллекции
485
     *
486
     * @return int
487
     */
488
    public function getOffset()
489
    {
490
        return $this->offset;
491
    }
492
493
    /**
494
     * Общее количество страниц при заданом лимиите на страницу
495
     *
496
     * @return float
497
     * @throws Exception
498
     */
499
    public function getPages() {
500
        return ceil($this->getFullCount() /  $this->getLimit());
501
    }
502
}