Completed
Pull Request — master (#221)
by Sergey
02:16
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 seregazhuk\PinterestBot\Api\Contracts\PaginatedResponse;
7
8
/**
9
 * Class Pagination
10
 * Iterate through results of Pinterest Api. By default iterator will return 50 first
11
 * pagination results. To change this behaviour specify another limit as the
12
 * constructor param. For no limits specify zero.
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 = self::DEFAULT_LIMIT)
39
    {
40
        $this->limit = $limit;
41
    }
42
43
    /**
44
     * Sets a callback to make requests. Should be a closure
45
     * that accepts a $bookmarks array as an argument.
46
     *
47
     * @param callable $callback
48
     * @return $this
49
     */
50
    public function paginateOver(callable $callback)
51
    {
52
        $this->callback = $callback;
53
54
        return $this;
55
    }
56
57
    /**
58
     * Retrieve an external iterator
59
     * @return Traversable
60
     */
61
    public function getIterator()
62
    {
63
        $resultsNum = 0;
64
65
        while (true) {
66
            $results = $this->getCurrentResults();
67
68
            if (empty($results)) return;
69
70
            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...
71
                $resultsNum++;
72
                yield $result;
73
74
                if ($this->paginationFinished($resultsNum)) {
75
                    return;
76
                }
77
            }
78
        }
79
80
        return;
81
    }
82
83
    /**
84
     * @return array
85
     */
86
    public function toArray()
87
    {
88
        return iterator_to_array($this->getIterator());
89
    }
90
91
    /**
92
     * @return array
93
     */
94
    protected function getCurrentResults()
95
    {
96
        $callback = $this->callback;
97
98
        $response = $callback($this->bookmarks);
99
100
        return $this->processResponse($response);
101
    }
102
103
    /**
104
     * @param PaginatedResponse $response
105
     * @return array
106
     */
107
    protected function processResponse(PaginatedResponse $response)
108
    {
109
        if ($response->isEmpty()) return [];
110
111
        $this->bookmarks = $response->getBookmarks();
112
113
        return $response->getResponseData();
114
    }
115
116
    /**
117
     * @param int $resultsNum
118
     * @return bool
119
     */
120
    protected function paginationFinished($resultsNum)
121
    {
122
        return $this->reachesLimit($resultsNum) || $this->checkEndBookMarks();
123
    }
124
125
    /**
126
     * Check if we get results limit in pagination.
127
     *
128
     * @param int $resultsNum
129
     *
130
     * @return bool
131
     */
132
    protected function reachesLimit($resultsNum)
133
    {
134
        return $this->limit && $resultsNum >= $this->limit;
135
    }
136
137
138
    /**
139
     * Checks for -end- substring in bookmarks. This is pinterest sign of
140
     * the finished pagination.
141
     *
142
     * @return bool
143
     */
144
    protected function checkEndBookMarks()
145
    {
146
        return !empty($this->bookmarks) && $this->bookmarks[0] == '-end-';
147
    }
148
}
149