Completed
Pull Request — master (#42)
by Chad
03:06
created

Collection::next()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
c 0
b 0
f 0
rs 9.3142
cc 2
eloc 14
nc 2
nop 0
1
<?php
2
3
namespace TraderInteractive\Api;
4
5
use DominionEnterprises\Util;
6
7
/**
8
 * Class for iterating index responses. Collections are readonly
9
 */
10
final 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 int
23
     */
24
    private $limit;
25
26
    /**
27
     * offset to give to API
28
     *
29
     * @var int
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 int
51
     */
52
    private $total;
53
54
    /**
55
     * pointer in the paginated results
56
     *
57
     * @var int
58
     */
59
    private $position;
60
61
    /**
62
     * A paginated set of elements from the API
63
     *
64
     * @var array
65
     */
66
    private $result;
67
68
    /**
69
     * Create a new collection
70
     *
71
     * @param Client $client client connection to the API
72
     * @param string $resource name of API resource to request
73
     * @param array $filters key value pair array of search filters
74
     */
75
    public function __construct(Client $client, $resource, array $filters = [])
76
    {
77
        Util::throwIfNotType(['string' => [$resource]], true);
78
79
        $this->client = $client;
80
        $this->resource = $resource;
81
        $this->filters = $filters;
82
        $this->rewind();
83
    }
84
85
    /**
86
     * @see Countable::count()
87
     *
88
     * @return int
89
     */
90
    public function count()
91
    {
92
        if ($this->position === -1) {
93
            $this->next();
94
        }
95
96
        return $this->total;
97
    }
98
99
    /**
100
     * @see Iterator::rewind()
101
     *
102
     * @return void
103
     */
104
    public function rewind()
105
    {
106
        $this->result = null;
0 ignored issues
show
Documentation Bug introduced by
It seems like null of type null is incompatible with the declared type array of property $result.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
107
        $this->offset = 0;
108
        $this->total = 0;
109
        $this->limit = 0;
110
        $this->position = -1;
111
    }
112
113
    /**
114
     * @see Iterator::key()
115
     *
116
     * @return int
117
     */
118 View Code Duplication
    public function key()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
119
    {
120
        if ($this->position === -1) {
121
            $this->next();
122
        }
123
124
        Util::ensure(false, empty($this->result), '\OutOfBoundsException', ['Collection contains no elements']);
125
126
        return $this->offset + $this->position;
127
    }
128
129
    /**
130
     * @see Iterator::valid()
131
     *
132
     * @return bool
133
     */
134
    public function valid()
135
    {
136
        if ($this->position === -1) {
137
            $this->next();
138
        }
139
140
        return $this->offset + $this->position < $this->total;
141
    }
142
143
    /**
144
     * @see Iterator::next()
145
     *
146
     * @return void
147
     */
148
    public function next()
149
    {
150
        ++$this->position;
151
152
        if ($this->position < $this->limit) {
153
            return;
154
        }
155
156
        $this->offset += $this->limit;
157
        $this->filters['offset'] = $this->offset;
158
        $indexResponse = $this->client->index($this->resource, $this->filters);
159
160
        $httpCode = $indexResponse->getHttpCode();
161
        Util::ensure(200, $httpCode, "Did not receive 200 from API. Instead received {$httpCode}");
162
163
        $response = $indexResponse->getResponse();
164
        $this->limit = $response['pagination']['limit'];
165
        $this->total = $response['pagination']['total'];
166
        $this->result = $response['result'];
167
        $this->position = 0;
168
    }
169
170
    /**
171
     * @see Iterator::current()
172
     *
173
     * @return array
174
     */
175 View Code Duplication
    public function current()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
176
    {
177
        if ($this->position === -1) {
178
            $this->next();
179
        }
180
181
        Util::ensure(
182
            true,
183
            array_key_exists($this->position, $this->result),
184
            '\OutOfBoundsException',
185
            ['Collection contains no element at current position']
186
        );
187
188
        return $this->result[$this->position];
189
    }
190
191
    /**
192
     * Returns the values from a single field this collection, identified by the given $key.
193
     *
194
     * @param string $key The name of the field for which the values will be returned.
195
     *
196
     * @return iterable
197
     */
198
    public function column($key)
199
    {
200
        foreach ($this as $item) {
201
            yield Util\Arrays::get($item, $key);
202
        }
203
    }
204
205
    /**
206
     * Return an iterable generator containing only the fields specified in the $keys array.
207
     *
208
     * @param array $keys The list of field names to be returned.
209
     *
210
     * @return \Generator
211
     */
212
    public function select(array $keys)
213
    {
214
        foreach ($this as $item) {
215
            $result = array_fill_keys($keys, null);
216
            Util\Arrays::copyIfKeysExist($item, $result, $keys);
217
            yield  $result;
218
        }
219
    }
220
}
221