Failed Conditions
Branch v3.x (aec8e0)
by Chad
01:59
created

src/Collection.php (3 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Chadicus\Marvel\Api;
4
5
use DominionEnterprises\Util;
6
7
/**
8
 * Class for iterating index response to the Marvel API. Collections are readonly.
9
 */
10
class Collection implements \Iterator, \Countable
11
{
12
    /**
13
     * API Client.
14
     *
15
     * @var Client
16
     */
17
    private $client;
18
19
    /**
20
     * Limit to give to API.
21
     *
22
     * @var integer
23
     */
24
    private $limit;
25
26
    /**
27
     * Offset to give to API.
28
     *
29
     * @var integer
30
     */
31
    private $offset;
32
33
    /**
34
     * Resource name for collection.
35
     *
36
     * @var string
37
     */
38
    private $resource;
39
40
    /**
41
     * Array of filters to pass to API.
42
     *
43
     * @var array
44
     */
45
    private $filters;
46
47
    /**
48
     * Total number of elements in the collection.
49
     *
50
     * @var integer
51
     */
52
    private $total;
53
54
    /**
55
     * Pointer in the paginated results.
56
     *
57
     * @var integer
58
     */
59
    private $position;
60
61
    /**
62
     * A paginated set of elements from the API.
63
     *
64
     * @var null|array
65
     */
66
    private $results;
67
68
    /**
69
     * A custom callable to return a defined type when iterating over the collection.
70
     *
71
     * @var callable
72
     */
73
    private $loader;
74
75
    /**
76
     * Create a new collection.
77
     *
78
     * @param Client   $client   A client connection to the API.
79
     * @param string   $resource The name of API resource to request.
80
     * @param array    $filters  A key value pair array of search filters.
81
     * @param callable $loader   A custom callable to use when iterating over the collection.
82
     */
83
    final public function __construct(Client $client, string $resource, array $filters = [], callable $loader = null)
84
    {
85
        Util::throwIfNotType(['string' => [$resource]], true);
86
87
        $this->client = $client;
88
        $this->resource = $resource;
89
        $this->filters = $filters;
90
        $this->loader = $loader;
91
        $this->rewind();
92
    }
93
94
    /**
95
     * Return the count elements in this collection, @see Countable::count().
96
     *
97
     * @return integer
98
     */
99
    final public function count()
100
    {
101
        if ($this->position === -1) {
102
            $this->next();
103
        }
104
105
        return $this->total;
106
    }
107
108
    /**
109
     * Rewind the Iterator to the first element, @see Iterator::rewind().
110
     *
111
     * @return void
112
     */
113
    final public function rewind()
114
    {
115
        $this->results = null;
116
        $this->offset = 0;
117
        $this->total = 0;
118
        $this->limit = 0;
119
        $this->position = -1;
120
    }
121
122
    /**
123
     * Return the key of the current element, @see Iterator::key().
124
     *
125
     * @return integer
126
     */
127
    final public function key()
128
    {
129
        if ($this->position === -1) {
130
            $this->next();
131
        }
132
133
        Util::ensure(false, empty($this->results), '\OutOfBoundsException', ['Collection contains no elements']);
134
135
        return $this->offset + $this->position;
136
    }
137
138
    /**
139
     * Checks if current position is valid, @see Iterator::valid().
140
     *
141
     * @return boolean
142
     */
143
    final public function valid()
144
    {
145
        if ($this->position === -1) {
146
            $this->next();
147
        }
148
149
        return $this->offset + $this->position < $this->total;
150
    }
151
152
    /**
153
     * Move forward to next element, @see Iterator::next().
154
     *
155
     * @return void
156
     */
157
    final public function next()
158
    {
159
        ++$this->position;
160
161
        if ($this->position < $this->limit) {
162
            return;
163
        }
164
165
        $this->offset += $this->limit;
166
        $this->filters['offset'] = $this->offset;
167
        $this->filters['limit'] = $this->limit === 0 ? 20 : $this->limit;
168
        $dataWrapper = $this->client->search($this->resource, $this->filters);
169
170
        $this->limit = $dataWrapper->getData()->getLimit();
0 ignored issues
show
The method getData() does not seem to exist on object<Psr\Http\Message\ResponseInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
171
        $this->total = $dataWrapper->getData()->getTotal();
0 ignored issues
show
The method getData() does not seem to exist on object<Psr\Http\Message\ResponseInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
172
        $this->results = $dataWrapper->getData()->getResults();
0 ignored issues
show
The method getData() does not seem to exist on object<Psr\Http\Message\ResponseInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
173
        $this->position = 0;
174
    }
175
176
    /**
177
     * Return the current element, @see Iterator::current().
178
     *
179
     * @return mixed Returns the element in the results array or a custom type defined by $loader.
180
     */
181
    final public function current()
182
    {
183
        if ($this->position === -1) {
184
            $this->next();
185
        }
186
187
        Util::ensure(
188
            true,
189
            array_key_exists($this->position, $this->results),
190
            '\OutOfBoundsException',
191
            ['Collection contains no element at current position']
192
        );
193
194
        if ($this->loader === null) {
195
            return $this->results[$this->position];
196
        }
197
198
        return call_user_func_array($this->loader, [$this->results[$this->position]]);
199
    }
200
}
201