Completed
Pull Request — master (#10)
by Dennis
02:26
created

PaginatedResponse::guardAndSetPagination()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 8.5906
c 0
b 0
f 0
cc 5
eloc 14
nc 5
nop 1
1
<?php declare(strict_types = 1);
2
3
namespace Link0\Bunq;
4
5
use ArrayAccess;
6
use InvalidArgumentException;
7
use IteratorAggregate;
8
use Traversable;
9
10
/**
11
 * Array (
12
 *   'Response' => [
13
 *     0 => [
14
 *       'Foo' => [
15
 *         'id' => 123,
16
 *       ],
17
 *     ],
18
 *     1 => [
19
 *       'Foo' => [
20
 *         'id' => 456,
21
 *       ],
22
 *     ],
23
 *
24
 *   ],
25
 *   'Pagination' => [
26
 *     'future_url' => '/v1/foo?newer_id=123',
27
 *     'newer_url' => '/v1/foo?newer_id=456',
28
 *     'older_url' => null,
29
 *   ]
30
 * )
31
 */
32
final class PaginatedResponse implements IteratorAggregate, ArrayAccess
33
{
34
    /**
35
     * @var Client
36
     */
37
    private $client;
38
39
    /**
40
     * @var array
41
     */
42
    private $list;
43
44
    /**
45
     * @var array
46
     */
47
    private $pagination;
48
49
    /**
50
     * @param Client $client
51
     */
52
    public function __construct(Client $client, array $body)
53
    {
54
        $this->client = $client;
55
56
        $this->guardAndSetResponseBody($body);
57
        $this->guardAndSetPagination($body);
58
    }
59
60
    /**
61
     * @param array $body
62
     * @return void
63
     */
64
    private function guardAndSetResponseBody(array $body)
65
    {
66
        if (!isset($body['Response'])) {
67
            throw new InvalidArgumentException("Response body should contain key 'Response'");
68
        }
69
        $this->list = $body['Response'];
70
    }
71
72
    /**
73
     * @param array $body
74
     * @return void
75
     */
76
    private function guardAndSetPagination(array $body)
77
    {
78
        $this->pagination = [
79
            'future_url' => null,
80
            'newer_url' => null,
81
            'older_url' => null,
82
        ];
83
84
        if (isset($body['Pagination'])) {
85
            $pagination = $body['Pagination'];
86
87
            if (!array_key_exists('future_url', $pagination)) {
88
                throw new InvalidArgumentException("Pagination should contain future_url");
89
            }
90
            if (!array_key_exists('newer_url', $pagination)) {
91
                throw new InvalidArgumentException("Pagination should contain newer_url");
92
            }
93
            if (!array_key_exists('older_url', $pagination)) {
94
                throw new InvalidArgumentException("Pagination should contain older_url");
95
            }
96
            $this->pagination = $pagination;
97
        }
98
    }
99
100
    /**
101
     * Retrieve an external iterator
102
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
103
     * @return Traversable An instance of an object implementing <b>Iterator</b> or
104
     * <b>Traversable</b>
105
     * @since 5.0.0
106
     */
107
    public function getIterator()
108
    {
109
        foreach ($this->list as $key => $value) {
110
            // mapResponse takes the struct and instantiates Value Objects
111
            yield $key => $this->client->mapResponse($key, $value);
112
        }
113
114
        if ($this->pagination['newer_url'] !== null) {
115
            /** @var PaginatedResponse $nextPagination */
116
            $nextPagination = $this->client->get($this->pagination['newer_url']);
117
118
            foreach ($nextPagination as $newKey => $newValue) {
119
                $this->list[] = $newValue;
120
                unset($nextPagination->list[$newKey]);
121
                yield $newKey => $newValue;
122
            }
123
        }
124
    }
125
126
    /**
127
     * Whether a offset exists
128
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
129
     * @param mixed $offset <p>
130
     * An offset to check for.
131
     * </p>
132
     * @return boolean true on success or false on failure.
133
     * </p>
134
     * <p>
135
     * The return value will be casted to boolean if non-boolean was returned.
136
     * @since 5.0.0
137
     */
138
    public function offsetExists($offset)
139
    {
140
        return array_key_exists($offset, $this->list);
141
    }
142
143
    /**
144
     * Offset to retrieve
145
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
146
     * @param mixed $offset <p>
147
     * The offset to retrieve.
148
     * </p>
149
     * @return mixed Can return all value types.
150
     * @since 5.0.0
151
     */
152
    public function offsetGet($offset)
153
    {
154
155
        return $this->list[$offset];
156
    }
157
158
    /**
159
     * Offset to set
160
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
161
     * @param mixed $offset <p>
162
     * The offset to assign the value to.
163
     * </p>
164
     * @param mixed $value <p>
165
     * The value to set.
166
     * </p>
167
     * @return void
168
     * @since 5.0.0
169
     */
170
    public function offsetSet($offset, $value)
171
    {
172
        throw new \LogicException("Unable to set value on immutable object");
173
    }
174
175
    /**
176
     * Offset to unset
177
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
178
     * @param mixed $offset <p>
179
     * The offset to unset.
180
     * </p>
181
     * @return void
182
     * @since 5.0.0
183
     */
184
    public function offsetUnset($offset)
185
    {
186
        throw new \LogicException("Unable to unset value on immutable object");
187
    }
188
}
189