Completed
Pull Request — master (#10)
by Dennis
02:38
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
            foreach ($this->client->get($this->pagination['newer_url']) as $newKey => $newValue) {
116
                $this->list[] = $newValue;
117
                yield $newKey => $newValue;
118
            }
119
        }
120
    }
121
122
    /**
123
     * Whether a offset exists
124
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
125
     * @param mixed $offset <p>
126
     * An offset to check for.
127
     * </p>
128
     * @return boolean true on success or false on failure.
129
     * </p>
130
     * <p>
131
     * The return value will be casted to boolean if non-boolean was returned.
132
     * @since 5.0.0
133
     */
134
    public function offsetExists($offset)
135
    {
136
        return array_key_exists($offset, $this->list);
137
    }
138
139
    /**
140
     * Offset to retrieve
141
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
142
     * @param mixed $offset <p>
143
     * The offset to retrieve.
144
     * </p>
145
     * @return mixed Can return all value types.
146
     * @since 5.0.0
147
     */
148
    public function offsetGet($offset)
149
    {
150
151
        return $this->list[$offset];
152
    }
153
154
    /**
155
     * Offset to set
156
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
157
     * @param mixed $offset <p>
158
     * The offset to assign the value to.
159
     * </p>
160
     * @param mixed $value <p>
161
     * The value to set.
162
     * </p>
163
     * @return void
164
     * @since 5.0.0
165
     */
166
    public function offsetSet($offset, $value)
167
    {
168
        throw new \LogicException("Unable to set value on immutable object");
169
    }
170
171
    /**
172
     * Offset to unset
173
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
174
     * @param mixed $offset <p>
175
     * The offset to unset.
176
     * </p>
177
     * @return void
178
     * @since 5.0.0
179
     */
180
    public function offsetUnset($offset)
181
    {
182
        throw new \LogicException("Unable to unset value on immutable object");
183
    }
184
}
185