Completed
Pull Request — master (#221)
by Sergey
02:28
created

Pagination::reachesLimit()   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 1
1
<?php
2
3
namespace seregazhuk\PinterestBot\Helpers;
4
5
use Traversable;
6
use seregazhuk\PinterestBot\Api\Contracts\PaginatedResponse;
7
8
/**
9
 * Class Pagination
10
 * Iterate through results of Api function call. By
11
 * default generator will return all pagination results.
12
 * To limit results, set $limit.
13
 *
14
 * @package seregazhuk\PinterestBot\Helpers
15
 */
16
class Pagination implements \IteratorAggregate
17
{
18
    const DEFAULT_LIMIT = 50;
19
20
    /**
21
     * @var int
22
     */
23
    protected $limit;
24
25
    /**
26
     * @var array
27
     */
28
    protected $bookmarks = [];
29
30
    /**
31
     * @var callable
32
     */
33
    protected $callback;
34
35
    /**
36
     * @param int $limit
37
     */
38
    public function __construct($limit = 0)
39
    {
40
        $this->limit = $limit;
41
    }
42
43
    /**
44
     * @param callable $callback
45
     * @return $this
46
     */
47
    public function paginateOver(callable $callback)
48
    {
49
        $this->callback = $callback;
50
51
        return $this;
52
    }
53
54
    /**
55
     * Retrieve an external iterator
56
     * @return Traversable
57
     */
58
    public function getIterator()
59
    {
60
        $resultsNum = 0;
61
62
        while (true) {
63
            $results = $this->getCurrentResults();
64
65
            if (empty($results)) return;
66
67
            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...
68
                $resultsNum++;
69
                yield $result;
70
71
                if ($this->paginationFinished($resultsNum)) {
72
                    return;
73
                }
74
            }
75
        }
76
77
        return;
78
    }
79
80
    /**
81
     * @return array
82
     */
83
    public function toArray()
84
    {
85
        return iterator_to_array($this->getIterator());
86
    }
87
88
    /**
89
     * @return array
90
     */
91
    protected function getCurrentResults()
92
    {
93
        $callback = $this->callback;
94
95
        $response = $callback($this->bookmarks);
96
97
        return $this->processResponse($response);
98
    }
99
100
    /**
101
     * @param PaginatedResponse $response
102
     * @return array
103
     */
104
    protected function processResponse(PaginatedResponse $response)
105
    {
106
        if ($response->isEmpty()) return [];
107
108
        $this->bookmarks = $response->getBookmarks();
109
110
        return $response->getResponseData();
111
    }
112
113
    /**
114
     * @param int $resultsNum
115
     * @return bool
116
     */
117
    protected function paginationFinished($resultsNum)
118
    {
119
        return $this->reachesLimit($resultsNum) || $this->checkEndBookMarks();
120
    }
121
122
    /**
123
     * Check if we get results limit in pagination.
124
     *
125
     * @param int $resultsNum
126
     *
127
     * @return bool
128
     */
129
    protected function reachesLimit($resultsNum)
130
    {
131
        return $this->limit && $resultsNum >= $this->limit;
132
    }
133
134
135
    /**
136
     * Checks for -end- substring in bookmarks. This is pinterest sign of
137
     * the finished pagination.
138
     *
139
     * @return bool
140
     */
141
    protected function checkEndBookMarks()
142
    {
143
        return !empty($this->bookmarks) && $this->bookmarks[0] == '-end-';
144
    }
145
}
146