1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of the BEAR.Resource package. |
4
|
|
|
* |
5
|
|
|
* @license http://opensource.org/licenses/MIT MIT |
6
|
|
|
*/ |
7
|
|
|
namespace BEAR\Resource; |
8
|
|
|
|
9
|
|
|
use BEAR\Resource\Exception\MethodException; |
10
|
|
|
use BEAR\Resource\Exception\OutOfBoundsException; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* @property string code |
14
|
|
|
* @property array headers |
15
|
|
|
* @property mixed body |
16
|
|
|
* @property string view |
17
|
|
|
*/ |
18
|
|
|
abstract class AbstractRequest implements RequestInterface, \ArrayAccess, \IteratorAggregate, \Serializable |
19
|
|
|
{ |
20
|
|
|
const GET = 'get'; |
21
|
|
|
const POST = 'post'; |
22
|
|
|
const PUT = 'put'; |
23
|
|
|
const PATCH = 'patch'; |
24
|
|
|
const DELETE = 'delete'; |
25
|
|
|
const HEAD = 'head'; |
26
|
|
|
const OPTIONS = 'options'; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* URI |
30
|
|
|
* |
31
|
|
|
* @var string |
32
|
|
|
*/ |
33
|
|
|
public $uri; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Resource object |
37
|
|
|
* |
38
|
|
|
* @var \BEAR\Resource\ResourceObject |
39
|
|
|
*/ |
40
|
|
|
public $resourceObject; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Method |
44
|
|
|
* |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
public $method = ''; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Query |
51
|
|
|
* |
52
|
|
|
* @var array |
53
|
|
|
*/ |
54
|
|
|
public $query = []; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Options |
58
|
|
|
* |
59
|
|
|
* @var array |
60
|
|
|
*/ |
61
|
|
|
public $options = []; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Request option (eager or lazy) |
65
|
|
|
* |
66
|
|
|
* @var string |
67
|
|
|
*/ |
68
|
|
|
public $in; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Links |
72
|
|
|
* |
73
|
|
|
* @var \BEAR\Resource\LinkType[] |
74
|
|
|
*/ |
75
|
|
|
public $links = []; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Request Result |
79
|
|
|
* |
80
|
|
|
* @var ResourceObject |
81
|
|
|
*/ |
82
|
|
|
protected $result; |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @var InvokerInterface |
86
|
|
|
*/ |
87
|
|
|
protected $invoker; |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* @var LinkerInterface |
91
|
|
|
*/ |
92
|
|
|
private $linker; |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* @param InvokerInterface $invoker |
96
|
|
|
* @param ResourceObject|null $ro |
97
|
|
|
* @param string $method |
98
|
|
|
* @param array $query |
99
|
|
|
* @param array $links |
100
|
|
|
* @param LinkerInterface|null $linker |
101
|
|
|
* |
102
|
|
|
* @throws MethodException |
103
|
|
|
*/ |
104
|
82 |
|
public function __construct( |
105
|
|
|
InvokerInterface $invoker, |
106
|
|
|
ResourceObject $ro = null, |
107
|
|
|
$method = Request::GET, |
108
|
|
|
array $query = [], |
109
|
|
|
array $links = [], |
110
|
|
|
LinkerInterface $linker = null |
111
|
|
|
) { |
112
|
82 |
|
$this->invoker = $invoker; |
113
|
82 |
|
$this->resourceObject = $ro; |
114
|
82 |
|
if (! in_array(strtolower($method), [self::GET, self::POST, self::PUT, self::PATCH, self::DELETE, self::HEAD, self::OPTIONS], true)) { |
115
|
1 |
|
throw new MethodException($method, 400); |
116
|
|
|
} |
117
|
82 |
|
$this->method = $method; |
118
|
82 |
|
$this->query = $query; |
119
|
82 |
|
$this->links = $links; |
120
|
82 |
|
$this->linker = $linker; |
121
|
82 |
|
} |
122
|
|
|
|
123
|
6 |
|
public function __toString() |
124
|
|
|
{ |
125
|
|
|
try { |
126
|
6 |
|
$this->invoke(); |
127
|
|
|
|
128
|
5 |
|
return (string) $this->result; |
129
|
1 |
|
} catch (\Exception $e) { |
130
|
1 |
|
error_log($e); |
131
|
|
|
|
132
|
1 |
|
return ''; |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* {@inheritdoc} |
138
|
|
|
*/ |
139
|
49 |
|
public function __invoke(array $query = null) |
140
|
|
|
{ |
141
|
49 |
|
if ($query !== null) { |
142
|
6 |
|
$this->query = array_merge($this->query, $query); |
143
|
|
|
} |
144
|
49 |
|
if ($this->links) { |
|
|
|
|
145
|
3 |
|
return $this->linker->invoke($this); |
146
|
|
|
} |
147
|
|
|
|
148
|
46 |
|
return $this->invoker->invoke($this); |
149
|
|
|
} |
150
|
|
|
|
151
|
3 |
|
public function __get($name) |
152
|
|
|
{ |
153
|
3 |
|
$this->result = $this->invoke(); |
154
|
|
|
|
155
|
3 |
|
return $this->result->$name; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
*{@inheritdoc} |
160
|
|
|
* |
161
|
|
|
* @throws OutOfBoundsException |
162
|
|
|
*/ |
163
|
1 |
|
public function offsetSet($offset, $value) |
164
|
|
|
{ |
165
|
1 |
|
throw new OutOfBoundsException(__METHOD__ . ' is unavailable.', 400); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* {@inheritdoc} |
170
|
|
|
* |
171
|
|
|
* @throws OutOfBoundsException |
172
|
|
|
*/ |
173
|
1 |
|
public function offsetUnset($offset) |
174
|
|
|
{ |
175
|
1 |
|
unset($offset); |
176
|
1 |
|
throw new OutOfBoundsException(__METHOD__ . ' is unavailable.', 400); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* {@inheritdoc} |
181
|
|
|
*/ |
182
|
26 |
|
public function request() |
183
|
|
|
{ |
184
|
26 |
|
if ($this->in == 'eager') { |
185
|
19 |
|
$this->result = $this->invoke(); |
186
|
|
|
|
187
|
17 |
|
return $this->result; |
188
|
|
|
} |
189
|
|
|
|
190
|
8 |
|
return $this; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* {@inheritdoc} |
195
|
|
|
* |
196
|
|
|
* @throws OutOfBoundsException |
197
|
|
|
*/ |
198
|
2 |
|
public function offsetGet($offset) |
199
|
|
|
{ |
200
|
2 |
|
$this->invoke(); |
201
|
2 |
|
if (! isset($this->result->body[$offset])) { |
202
|
1 |
|
throw new OutOfBoundsException("[$offset] for object[" . get_class($this->result) . ']', 400); |
203
|
|
|
} |
204
|
|
|
|
205
|
1 |
|
return $this->result->body[$offset]; |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
/** |
209
|
|
|
* {@inheritdoc} |
210
|
|
|
*/ |
211
|
2 |
|
public function offsetExists($offset) |
212
|
|
|
{ |
213
|
2 |
|
$this->invoke(); |
214
|
|
|
|
215
|
2 |
|
return isset($this->result->body[$offset]); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* {@inheritdoc} |
220
|
|
|
*/ |
221
|
1 |
|
public function getIterator() |
222
|
|
|
{ |
223
|
1 |
|
$this->invoke(); |
224
|
1 |
|
$isArray = (is_array($this->result->body) || $this->result->body instanceof \Traversable); |
225
|
1 |
|
$iterator = $isArray ? new \ArrayIterator($this->result->body) : new \ArrayIterator([]); |
226
|
|
|
|
227
|
1 |
|
return $iterator; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* {@inheritdoc} |
232
|
|
|
*/ |
233
|
4 |
|
public function hash() |
234
|
|
|
{ |
235
|
4 |
|
return md5(get_class($this->resourceObject) . $this->method . serialize($this->query) . serialize($this->links)); |
236
|
|
|
} |
237
|
|
|
|
238
|
|
|
/** |
239
|
|
|
* {@inheritdoc} |
240
|
|
|
*/ |
241
|
1 |
|
public function serialize() |
242
|
|
|
{ |
243
|
1 |
|
return serialize($this->invoke()); |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* {@inheritdoc} |
248
|
|
|
*/ |
249
|
1 |
|
public function unserialize($serialized) |
250
|
|
|
{ |
251
|
1 |
|
return unserialize($serialized); |
252
|
|
|
} |
253
|
|
|
|
254
|
34 |
|
private function invoke() : ResourceObject |
255
|
|
|
{ |
256
|
34 |
|
if ($this->result === null) { |
257
|
|
|
/* @noinspection ImplicitMagicMethodCallInspection */ |
258
|
33 |
|
$this->result = $this->__invoke(); |
259
|
|
|
} |
260
|
|
|
|
261
|
31 |
|
return $this->result; |
262
|
|
|
} |
263
|
|
|
} |
264
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.