Completed
Pull Request — master (#245)
by Sergey
04:32
created

Pagination::processResponse()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
3
namespace seregazhuk\PinterestBot\Helpers;
4
5
use Traversable;
6
use EmptyIterator;
7
use IteratorAggregate;
8
use seregazhuk\PinterestBot\Api\Response;
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. Should be a closure.
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)) return new EmptyIterator();
84
85
        return $this->processCallback();
86
    }
87
88
    /**
89
     * @param int $offset
90
     * @return $this
91
     */
92
    public function skip($offset)
93
    {
94
        $this->offset = $offset;
95
96
        return $this;
97
    }
98
99
    /**
100
     * @param int $limit
101
     * @return $this
102
     */
103
    public function take($limit)
104
    {
105
        $this->limit = $limit;
106
107
        return $this;
108
    }
109
110
    /**
111
     * @return array
112
     */
113
    public function toArray()
114
    {
115
        return iterator_to_array($this->getIterator());
116
    }
117
118
119
    /**
120
     * Check if we execGet results limit in pagination.
121
     *
122
     * @param int $resultsNum
123
     *
124
     * @return bool
125
     */
126
    protected function reachesLimit($resultsNum)
127
    {
128
        return $this->limit && $resultsNum >= $this->limit;
129
    }
130
131
    /**
132
     * @return \Generator|void
133
     */
134
    protected function processCallback()
135
    {
136
        $this->resultsNum = 0;
137
        $this->processed = 0;
138
        $callback = $this->callback;
139
140
        while (true) {
141
            /** @var Response $response */
142
            $response = $callback();
143
144
            if ($response->isEmpty()) return;
145
146
            foreach ($response->getResponseData() as $result) {
0 ignored issues
show
Bug introduced by
The expression $response->getResponseData() of type array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
147
                $this->processed++;
148
149
                if ($this->processed > $this->offset) {
150
                    yield $result;
151
                    $this->resultsNum++;
152
                }
153
154
                if ($this->reachesLimit($this->resultsNum)) return;
155
            }
156
157
            if (!$response->hasBookmarks()) return;
158
        }
159
    }
160
}
161