Completed
Pull Request — master (#42)
by Chad
04:56
created

Collection::column()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 3
nc 2
nop 1
1
<?php
2
3
namespace TraderInteractive\Api;
4
5
use TraderInteractive\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 ClientInterface
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|null
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(ClientInterface $client, string $resource, array $filters = [])
76
    {
77
        $this->client = $client;
78
        $this->resource = $resource;
79
        $this->filters = $filters;
80
        $this->rewind();
81
    }
82
83
    /**
84
     * @see Countable::count()
85
     *
86
     * @return integer
87
     */
88
    public function count() : int
89
    {
90
        if ($this->position === -1) {
91
            $this->next();
92
        }
93
94
        return $this->total;
95
    }
96
97
    /**
98
     * @see Iterator::rewind()
99
     *
100
     * @return void
101
     */
102
    public function rewind()
103
    {
104
        $this->result = null;
105
        $this->offset = 0;
106
        $this->total = 0;
107
        $this->limit = 0;
108
        $this->position = -1;
109
    }
110
111
    /**
112
     * @see Iterator::key()
113
     *
114
     * @return integer
115
     */
116 View Code Duplication
    public function key() : int
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...
117
    {
118
        if ($this->position === -1) {
119
            $this->next();
120
        }
121
122
        Util::ensure(false, empty($this->result), '\OutOfBoundsException', ['Collection contains no elements']);
123
124
        return $this->offset + $this->position;
125
    }
126
127
    /**
128
     * @see Iterator::valid()
129
     *
130
     * @return bool
131
     */
132
    public function valid() : bool
133
    {
134
        if ($this->position === -1) {
135
            $this->next();
136
        }
137
138
        return $this->offset + $this->position < $this->total;
139
    }
140
141
    /**
142
     * @see Iterator::next()
143
     *
144
     * @return void
145
     */
146
    public function next()
147
    {
148
        ++$this->position;
149
150
        if ($this->position < $this->limit) {
151
            return;
152
        }
153
154
        $this->offset += $this->limit;
155
        $this->filters['offset'] = $this->offset;
156
        $indexResponse = $this->client->index($this->resource, $this->filters);
157
158
        $httpCode = $indexResponse->getHttpCode();
159
        Util::ensure(200, $httpCode, "Did not receive 200 from API. Instead received {$httpCode}");
160
161
        $response = $indexResponse->getResponse();
162
        $this->limit = $response['pagination']['limit'];
163
        $this->total = $response['pagination']['total'];
164
        $this->result = $response['result'];
165
        $this->position = 0;
166
    }
167
168
    /**
169
     * @see Iterator::current()
170
     *
171
     * @return array
172
     */
173 View Code Duplication
    public function current() : array
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...
174
    {
175
        if ($this->position === -1) {
176
            $this->next();
177
        }
178
179
        Util::ensure(
180
            true,
181
            array_key_exists($this->position, $this->result),
182
            '\OutOfBoundsException',
183
            ['Collection contains no element at current position']
184
        );
185
186
        return $this->result[$this->position];
187
    }
188
189
    /**
190
     * Returns the values from a single field this collection, identified by the given $key.
191
     *
192
     * @param string $key The name of the field for which the values will be returned.
193
     *
194
     * @return \Iterator
195
     */
196
    public function column(string $key) : \Iterator
197
    {
198
        foreach ($this as $item) {
199
            yield Util\Arrays::get($item, $key);
200
        }
201
    }
202
203
    /**
204
     * Return an iterable generator containing only the fields specified in the $keys array.
205
     *
206
     * @param array $keys The list of field names to be returned.
207
     *
208
     * @return \Generator
209
     */
210
    public function select(array $keys) : \Iterator
211
    {
212
        foreach ($this as $item) {
213
            $result = array_fill_keys($keys, null);
214
            Util\Arrays::copyIfKeysExist($item, $result, $keys);
215
            yield  $result;
216
        }
217
    }
218
}
219