Completed
Pull Request — master (#237)
by Sergey
02:43
created

Pagination::checkEndBookMarks()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 2
eloc 2
nc 2
nop 0
1
<?php
2
3
namespace seregazhuk\PinterestBot\Helpers;
4
5
use Traversable;
6
use IteratorAggregate;
7
use seregazhuk\PinterestBot\Api\Response;
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 array
29
     */
30
    protected $bookmarks = [];
31
32
    /**
33
     * @var callable
34
     */
35
    protected $callback;
36
37
    /**
38
     * @var int
39
     */
40
    protected $offset;
41
42
    /**
43
     * @param int $limit
44
     */
45
    public function __construct($limit = self::DEFAULT_LIMIT)
46
    {
47
        $this->limit = $limit;
48
    }
49
50
    /**
51
     * Sets a callback to make requests. Should be a closure
52
     * that accepts a $bookmarks array as an argument.
53
     *
54
     * @param callable $callback
55
     * @return $this
56
     */
57
    public function paginateOver(callable $callback)
58
    {
59
        $this->callback = $callback;
60
61
        return $this;
62
    }
63
64
    /**
65
     * Syntax sugar for getIterator method
66
     * @return Traversable
67
     */
68
    public function get()
69
    {
70
        return $this->getIterator();
71
    }
72
73
    /**
74
     * Retrieve an external iterator
75
     * @return Traversable
76
     */
77
    public function getIterator()
78
    {
79
        $resultsNum = 0;
80
        $processed = 0;
81
82
        while (true) {
83
            $results = $this->getCurrentResults();
84
85
            if (empty($results)) return;
86
87
            foreach ($results as $result) {
0 ignored issues
show
Bug introduced by
The expression $results 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...
88
                $processed++;
89
90
                if($processed > $this->offset) {
91
                    yield $result;
92
                    $resultsNum++;
93
                }
94
95
                if ($this->reachesLimit($resultsNum)) return;
96
            }
97
98
            if (empty($this->bookmarks)) return;
99
        }
100
    }
101
102
    /**
103
     * @param int $offset
104
     * @return $this
105
     */
106
    public function skip($offset)
107
    {
108
        $this->offset = $offset;
109
110
        return $this;
111
    }
112
113
    /**
114
     * @param int $limit
115
     * @return $this
116
     */
117
    public function take($limit)
118
    {
119
        $this->limit = $limit;
120
121
        return $this;
122
    }
123
124
    /**
125
     * @return array
126
     */
127
    public function toArray()
128
    {
129
        return iterator_to_array($this->getIterator());
130
    }
131
132
    /**
133
     * @return array
134
     */
135
    protected function getCurrentResults()
136
    {
137
        $callback = $this->callback;
138
139
        /** @var Response $response */
140
        $response = $callback($this->bookmarks);
141
142
        return $this->processResponse($response);
143
    }
144
145
    /**
146
     * @param PaginatedResponse $response
147
     * @return array
148
     */
149
    protected function processResponse(PaginatedResponse $response)
150
    {
151
        if ($response->isEmpty()) return [];
152
153
        $this->bookmarks = $response->getBookmarks();
154
155
        return $response->getResponseData();
156
    }
157
158
    /**
159
     * Check if we get results limit in pagination.
160
     *
161
     * @param int $resultsNum
162
     *
163
     * @return bool
164
     */
165
    protected function reachesLimit($resultsNum)
166
    {
167
        return $this->limit && $resultsNum >= $this->limit;
168
    }
169
}
170