1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Anax\RemServer; |
4
|
|
|
|
5
|
|
|
use Anax\Commons\ContainerInjectableInterface; |
6
|
|
|
use Anax\Commons\ContainerInjectableTrait; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* A controller for the REM Server. |
10
|
|
|
*/ |
11
|
|
|
class RemServerController implements ContainerInjectableInterface |
12
|
|
|
{ |
13
|
|
|
use ContainerInjectableTrait; |
14
|
|
|
|
15
|
|
|
|
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Initiate the REM server before each action, if it has not already |
19
|
|
|
* some dataset(s). |
20
|
|
|
* |
21
|
|
|
* @return void |
22
|
|
|
*/ |
23
|
|
|
public function initialize() : void |
24
|
|
|
{ |
25
|
|
|
$rem = $this->di->get("remserver"); |
26
|
|
|
|
27
|
|
|
if (!$rem->hasDataset()) { |
28
|
|
|
$rem->init(); |
29
|
|
|
} |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
|
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Init or re-init the REM Server. |
36
|
|
|
* |
37
|
|
|
* @return array |
38
|
|
|
*/ |
39
|
|
View Code Duplication |
public function initActionGet() : array |
|
|
|
|
40
|
|
|
{ |
41
|
|
|
$rem = $this->di->get("remserver"); |
42
|
|
|
$rem->init(); |
43
|
|
|
$json = [ |
44
|
|
|
"message" => "The session is initiated with the default dataset(s).", |
45
|
|
|
"dataset" => $rem->getDefaultDataset(), |
46
|
|
|
]; |
47
|
|
|
return [$json]; |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
|
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Get a dataset $key or parts of it by using the querystring. |
54
|
|
|
* |
55
|
|
|
* @param array $args variadic argument containg all parts of the |
56
|
|
|
* request. |
57
|
|
|
* |
58
|
|
|
* @return array |
59
|
|
|
*/ |
60
|
|
|
public function catchAllGet(...$args) : array |
61
|
|
|
{ |
62
|
|
|
$dataSetKey = $args[0] ?? null; |
63
|
|
|
$itemId = $args[1] ?? null; |
64
|
|
|
$rest = $args[2] ?? null; |
65
|
|
|
|
66
|
|
|
// Type check that $itemId is int |
67
|
|
|
|
68
|
|
|
if ($dataSetKey && is_null($itemId)) { |
69
|
|
|
return $this->getDataset($dataSetKey); |
70
|
|
|
} elseif ($dataSetKey && !is_null($itemId) && is_null($rest)) { |
71
|
|
|
return $this->getItem($dataSetKey, $itemId); |
|
|
|
|
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
return $this->catchAll($args); |
|
|
|
|
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
|
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Get a dataset $key or parts of it by using the querystring. |
81
|
|
|
* |
82
|
|
|
* @param array $key to the dataset to get. |
83
|
|
|
* |
84
|
|
|
* @return array |
85
|
|
|
*/ |
86
|
|
|
public function getDataset($key) : array |
87
|
|
|
{ |
88
|
|
|
$request = $this->di->get("request"); |
89
|
|
|
$dataset = $this->di->get("remserver")->getDataset($key); |
90
|
|
|
$offset = $request->getGet("offset", 0); |
91
|
|
|
$limit = $request->getGet("limit", 25); |
92
|
|
|
$json = [ |
93
|
|
|
"data" => array_slice($dataset, $offset, $limit), |
94
|
|
|
"offset" => $offset, |
95
|
|
|
"limit" => $limit, |
96
|
|
|
"total" => count($dataset) |
97
|
|
|
]; |
98
|
|
|
return [$json]; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
|
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Get one item from the dataset. |
105
|
|
|
* |
106
|
|
|
* @param string $key for the dataset |
107
|
|
|
* @param int $itemId for the item to get |
108
|
|
|
* |
109
|
|
|
* @return array |
110
|
|
|
*/ |
111
|
|
View Code Duplication |
public function getItem(string $key, int $itemId) : array |
|
|
|
|
112
|
|
|
{ |
113
|
|
|
$item = $this->di->get("remserver")->getItem($key, $itemId); |
114
|
|
|
if (!$item) { |
115
|
|
|
return [["message" => "The item is not found."]]; |
116
|
|
|
} |
117
|
|
|
return [$item]; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
|
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Create a new item by getting the entry from the request body and add |
124
|
|
|
* to the dataset. |
125
|
|
|
* |
126
|
|
|
* @param string $key for the dataset |
|
|
|
|
127
|
|
|
* |
128
|
|
|
* @return array |
129
|
|
|
*/ |
130
|
|
|
public function catchAllPost(...$args) : array |
131
|
|
|
{ |
132
|
|
|
$dataSetKey = $args[0] ?? null; |
133
|
|
|
|
134
|
|
|
if (is_null($dataSetKey)) { |
135
|
|
|
return $this->catchAll(); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
try { |
139
|
|
|
$entry = $this->getRequestBody(); |
140
|
|
|
} catch (Exception $e) { |
141
|
|
|
return $this->di->get("response")->sendJson( |
142
|
|
|
["message" => "500. HTTP request body is not an object/array or valid JSON."], |
143
|
|
|
500 |
144
|
|
|
); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
$item = $this->di->get("remserver")->addItem($dataSetKey, $entry); |
148
|
|
|
return [$item]; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Upsert/replace an item in the dataset, entry is taken from request body. |
154
|
|
|
* |
155
|
|
|
* @param string $key for the dataset |
|
|
|
|
156
|
|
|
* @param string $itemId where to save the entry |
|
|
|
|
157
|
|
|
* |
158
|
|
|
* @return void |
159
|
|
|
*/ |
160
|
|
|
public function catchAllPut(...$args) : array |
161
|
|
|
{ |
162
|
|
|
$dataSetKey = $args[0] ?? null; |
163
|
|
|
$itemId = $args[1] ?? null; |
164
|
|
|
|
165
|
|
|
if (!($dataSetKey && !is_null($itemId))) { |
166
|
|
|
return $this->catchAll($args); |
|
|
|
|
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
// This should be managed through the typed route |
170
|
|
|
$itemId = intval($itemId); |
171
|
|
|
|
172
|
|
|
try { |
173
|
|
|
$entry = $this->getRequestBody(); |
174
|
|
|
} catch (Exception $e) { |
175
|
|
|
return $this->di->get("response")->sendJson( |
176
|
|
|
["message" => "500. HTTP request body is not an object/array or valid JSON."], |
177
|
|
|
500 |
178
|
|
|
); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
$item = $this->di->get("remserver")->upsertItem($dataSetKey, $itemId, $entry); |
182
|
|
|
return [$item]; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
|
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Delete an item from the dataset. |
189
|
|
|
* |
190
|
|
|
* @param string $key for the dataset |
|
|
|
|
191
|
|
|
* @param string $itemId for the item to delete |
|
|
|
|
192
|
|
|
* |
193
|
|
|
* @return array |
194
|
|
|
*/ |
195
|
|
|
public function catchAllDelete(...$args) : array |
196
|
|
|
{ |
197
|
|
|
$dataSetKey = $args[0] ?? null; |
198
|
|
|
$itemId = $args[1] ?? null; |
199
|
|
|
|
200
|
|
|
if (!($dataSetKey && !is_null($itemId))) { |
201
|
|
|
return $this->catchAll($args); |
|
|
|
|
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
// This should be managed through the typed route |
205
|
|
|
$itemId = intval($itemId); |
206
|
|
|
|
207
|
|
|
$this->di->get("remserver")->deleteItem($dataSetKey, $itemId); |
208
|
|
|
$json = [ |
209
|
|
|
"message" => "Item id '$itemId' was deleted from dataset '$dataSetKey'.", |
210
|
|
|
]; |
211
|
|
|
return [$json]; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
|
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* Get the request body from the HTTP request and treat it as |
218
|
|
|
* JSON data. |
219
|
|
|
* |
220
|
|
|
* @throws Exception when request body is invalid JSON. |
221
|
|
|
* |
222
|
|
|
* @return mixed as the JSON converted content. |
223
|
|
|
*/ |
224
|
|
|
protected function getRequestBody() |
225
|
|
|
{ |
226
|
|
|
$entry = $this->di->get("request")->getBody(); |
227
|
|
|
$entry = json_decode($entry, true); |
228
|
|
|
|
229
|
|
|
if (is_null($entry)) { |
230
|
|
|
throw new Exception("Could not read HTTP request body as JSON."); |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
return $entry; |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
|
237
|
|
|
|
238
|
|
|
/** |
239
|
|
|
* Show a message that the route is unsupported, a local 404. |
240
|
|
|
* |
241
|
|
|
* @return void |
242
|
|
|
*/ |
243
|
|
|
public function catchAll() |
244
|
|
|
{ |
245
|
|
|
return [["message" => "404. The api/ does not support that."], 404]; |
246
|
|
|
} |
247
|
|
|
} |
248
|
|
|
|
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.