Pagination::getIterator()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 2 Features 1
Metric Value
cc 2
eloc 3
c 4
b 2
f 1
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
3
namespace seregazhuk\PinterestBot\Helpers;
4
5
use Traversable;
6
use EmptyIterator;
7
use IteratorAggregate;
8
use seregazhuk\PinterestBot\Api\Contracts\PaginatedResponse;
9
10
/**
11
 * Class Pagination
12
 * Iterate through results of Pinterest Api. By default iterator will return 50 first
13
 * pagination results. To change this behaviour specify another limit as the
14
 * constructor param. For no limits specify zero.
15
 *
16
 * @package seregazhuk\PinterestBot\Helpers
17
 */
18
class Pagination implements IteratorAggregate
19
{
20
    const DEFAULT_LIMIT = 50;
21
22
    /**
23
     * @var int
24
     */
25
    protected $limit;
26
27
    /**
28
     * @var callable
29
     */
30
    protected $callback;
31
32
    /**
33
     * @var int
34
     */
35
    protected $offset;
36
37
    /**
38
     * @var int
39
     */
40
    protected $resultsNum;
41
42
    /**
43
     * @var int
44
     */
45
    protected $processed;
46
47
    /**
48
     * @param int $limit
49
     */
50
    public function __construct($limit = self::DEFAULT_LIMIT)
51
    {
52
        $this->limit = $limit;
53
    }
54
55
    /**
56
     * Sets a callback to make requests. Callback should return PaginatedResponse object.
57
     *
58
     * @param callable $callback
59
     * @return $this
60
     */
61
    public function paginateOver(callable $callback)
62
    {
63
        $this->callback = $callback;
64
65
        return $this;
66
    }
67
68
    /**
69
     * Syntax sugar for getIterator method
70
     * @return Traversable
71
     */
72
    public function get()
73
    {
74
        return $this->getIterator();
75
    }
76
77
    /**
78
     * Retrieve an external iterator
79
     * @return Traversable
80
     */
81
    public function getIterator()
82
    {
83
        if (empty($this->callback)) {
84
            return new EmptyIterator();
85
        }
86
87
        return $this->processCallback();
88
    }
89
90
    /**
91
     * @param int $offset
92
     * @return $this
93
     */
94
    public function skip($offset)
95
    {
96
        $this->offset = $offset;
97
98
        return $this;
99
    }
100
101
    /**
102
     * @param int $limit
103
     * @return $this
104
     */
105
    public function take($limit)
106
    {
107
        $this->limit = $limit;
108
109
        return $this;
110
    }
111
112
    /**
113
     * @return array
114
     */
115
    public function toArray()
116
    {
117
        return iterator_to_array($this->getIterator());
118
    }
119
120
    /**
121
     * Check if we execGet results limit in pagination.
122
     *
123
     * @param int $resultsNum
124
     *
125
     * @return bool
126
     */
127
    protected function reachesLimit($resultsNum)
128
    {
129
        return $this->limit && $resultsNum >= $this->limit;
130
    }
131
132
    /**
133
     * @return \Generator|void
134
     */
135
    protected function processCallback()
136
    {
137
        $this->resultsNum = 0;
138
        $this->processed = 0;
139
140
        while (true) {
141
            /** @var PaginatedResponse $response */
142
            $response = call_user_func($this->callback);
143
144
            if ($response->isEmpty()) {
145
                return;
146
            }
147
148
            foreach ($this->getResultsFromResponse($response) as $result) {
149
                $this->processed++;
150
151
                if ($this->processed > $this->offset) {
152
                    yield $result;
153
                    $this->resultsNum++;
154
                }
155
156
                if ($this->reachesLimit($this->resultsNum)) {
157
                    return;
158
                }
159
            }
160
161
            if (!$response->hasBookmarks()) {
162
                return;
163
            }
164
        }
165
    }
166
167
    /**
168
     * @param $response
169
     * @return array
170
     */
171
    protected function getResultsFromResponse(PaginatedResponse $response)
172
    {
173
        $results = $response->getResponseData();
174
175
        return $results === false ? [] : $results;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $results === false ? array() : $results also could return the type true which is incompatible with the documented return type array.
Loading history...
176
    }
177
}
178