|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Bluz Framework Component |
|
4
|
|
|
* |
|
5
|
|
|
* @copyright Bluz PHP Team |
|
6
|
|
|
* @link https://github.com/bluzphp/framework |
|
7
|
|
|
*/ |
|
8
|
|
|
|
|
9
|
|
|
declare(strict_types=1); |
|
10
|
|
|
|
|
11
|
|
|
namespace Bluz\Controller\Mapper; |
|
12
|
|
|
|
|
13
|
|
|
use Bluz\Application\Application; |
|
14
|
|
|
use Bluz\Application\Exception\ForbiddenException; |
|
15
|
|
|
use Bluz\Application\Exception\NotAcceptableException; |
|
16
|
|
|
use Bluz\Application\Exception\NotAllowedException; |
|
17
|
|
|
use Bluz\Application\Exception\NotImplementedException; |
|
18
|
|
|
use Bluz\Common\Exception\CommonException; |
|
19
|
|
|
use Bluz\Common\Exception\ComponentException; |
|
20
|
|
|
use Bluz\Controller\Controller; |
|
21
|
|
|
use Bluz\Controller\ControllerException; |
|
22
|
|
|
use Bluz\Crud\AbstractCrud; |
|
23
|
|
|
use Bluz\Http\RequestMethod; |
|
24
|
|
|
use Bluz\Proxy\Acl; |
|
25
|
|
|
use Bluz\Proxy\Request; |
|
26
|
|
|
use Bluz\Proxy\Router; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* Mapper for controller |
|
30
|
|
|
* |
|
31
|
|
|
* @package Bluz\Rest |
|
32
|
|
|
* @author Anton Shevchuk |
|
33
|
|
|
*/ |
|
34
|
|
|
abstract class AbstractMapper |
|
35
|
|
|
{ |
|
36
|
|
|
/** |
|
37
|
|
|
* @var string HTTP Method |
|
38
|
|
|
*/ |
|
39
|
|
|
protected $method = RequestMethod::GET; |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* @var string |
|
43
|
|
|
*/ |
|
44
|
|
|
protected $module; |
|
45
|
|
|
|
|
46
|
|
|
/** |
|
47
|
|
|
* @var string |
|
48
|
|
|
*/ |
|
49
|
|
|
protected $controller; |
|
50
|
|
|
|
|
51
|
|
|
/** |
|
52
|
|
|
* @var array identifier |
|
53
|
|
|
*/ |
|
54
|
|
|
protected $primary; |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* @var string relation list |
|
58
|
|
|
*/ |
|
59
|
|
|
protected $relation; |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* @var string relation Id |
|
63
|
|
|
*/ |
|
64
|
|
|
protected $relationId; |
|
65
|
|
|
|
|
66
|
|
|
/** |
|
67
|
|
|
* @var array params of query |
|
68
|
|
|
*/ |
|
69
|
|
|
protected $params = []; |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* @var array query data |
|
73
|
|
|
*/ |
|
74
|
|
|
protected $data = []; |
|
75
|
|
|
|
|
76
|
|
|
/** |
|
77
|
|
|
* @var AbstractCrud instance of CRUD |
|
78
|
|
|
*/ |
|
79
|
|
|
protected $crud; |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* [ |
|
83
|
|
|
* METHOD => Link { |
|
84
|
|
|
* 'module' => 'module', |
|
85
|
|
|
* 'controller' => 'controller', |
|
86
|
|
|
* 'acl' => 'privilege', |
|
87
|
|
|
* 'fields' => ['id', ... ] |
|
88
|
|
|
* }, |
|
89
|
|
|
* ] |
|
90
|
|
|
* |
|
91
|
|
|
* @var Link[] |
|
92
|
|
|
*/ |
|
93
|
|
|
protected $map = []; |
|
94
|
|
|
|
|
95
|
|
|
/** |
|
96
|
|
|
* Prepare params |
|
97
|
|
|
* |
|
98
|
|
|
* @return array |
|
99
|
|
|
*/ |
|
100
|
|
|
abstract protected function prepareParams(): array; |
|
101
|
|
|
|
|
102
|
|
|
/** |
|
103
|
|
|
* @param AbstractCrud $crud |
|
104
|
|
|
*/ |
|
105
|
16 |
|
public function __construct(AbstractCrud $crud) |
|
106
|
|
|
{ |
|
107
|
16 |
|
$this->crud = $crud; |
|
108
|
16 |
|
} |
|
109
|
|
|
|
|
110
|
|
|
/** |
|
111
|
|
|
* Add mapping data |
|
112
|
|
|
* |
|
113
|
|
|
* @param string $method |
|
114
|
|
|
* @param string $module |
|
115
|
|
|
* @param string $controller |
|
116
|
|
|
* @return Link |
|
117
|
|
|
*/ |
|
118
|
15 |
|
public function addMap($method, $module, $controller) : Link |
|
119
|
|
|
{ |
|
120
|
15 |
|
return $this->map[strtoupper($method)] = new Link($module, $controller); |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
/** |
|
124
|
|
|
* Add param to data, for example - setup foreign keys on fly |
|
125
|
|
|
* |
|
126
|
|
|
* @return void |
|
127
|
|
|
*/ |
|
128
|
|
|
public function addParam($name, $value) |
|
129
|
|
|
{ |
|
130
|
|
|
$this->data[$name] = $value; |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
/** |
|
134
|
|
|
* Add mapping for HEAD method |
|
135
|
|
|
* |
|
136
|
|
|
* @param string $module |
|
137
|
|
|
* @param string $controller |
|
138
|
|
|
* @return Link |
|
139
|
|
|
*/ |
|
140
|
|
|
public function head($module, $controller) : Link |
|
141
|
|
|
{ |
|
142
|
|
|
return $this->addMap(RequestMethod::HEAD, $module, $controller); |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* Add mapping for GET method |
|
147
|
|
|
* |
|
148
|
|
|
* @param string $module |
|
149
|
|
|
* @param string $controller |
|
150
|
|
|
* @return Link |
|
151
|
|
|
*/ |
|
152
|
|
|
public function get($module, $controller) : Link |
|
153
|
|
|
{ |
|
154
|
|
|
return $this->addMap(RequestMethod::GET, $module, $controller); |
|
155
|
|
|
} |
|
156
|
|
|
|
|
157
|
|
|
/** |
|
158
|
|
|
* Add mapping for POST method |
|
159
|
|
|
* |
|
160
|
|
|
* @param string $module |
|
161
|
|
|
* @param string $controller |
|
162
|
|
|
* @return Link |
|
163
|
|
|
*/ |
|
164
|
|
|
public function post($module, $controller) : Link |
|
165
|
|
|
{ |
|
166
|
|
|
return $this->addMap(RequestMethod::POST, $module, $controller); |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
/** |
|
170
|
|
|
* Add mapping for PATCH method |
|
171
|
|
|
* |
|
172
|
|
|
* @param string $module |
|
173
|
|
|
* @param string $controller |
|
174
|
|
|
* @return Link |
|
175
|
|
|
*/ |
|
176
|
|
|
public function patch($module, $controller) : Link |
|
177
|
|
|
{ |
|
178
|
|
|
return $this->addMap(RequestMethod::PATCH, $module, $controller); |
|
179
|
|
|
} |
|
180
|
|
|
|
|
181
|
|
|
/** |
|
182
|
|
|
* Add mapping for PUT method |
|
183
|
|
|
* |
|
184
|
|
|
* @param string $module |
|
185
|
|
|
* @param string $controller |
|
186
|
|
|
* @return Link |
|
187
|
|
|
*/ |
|
188
|
|
|
public function put($module, $controller) : Link |
|
189
|
|
|
{ |
|
190
|
|
|
return $this->addMap(RequestMethod::PUT, $module, $controller); |
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
|
|
/** |
|
194
|
|
|
* Add mapping for DELETE method |
|
195
|
|
|
* |
|
196
|
|
|
* @param string $module |
|
197
|
|
|
* @param string $controller |
|
198
|
|
|
* @return Link |
|
199
|
|
|
*/ |
|
200
|
|
|
public function delete($module, $controller) : Link |
|
201
|
|
|
{ |
|
202
|
|
|
return $this->addMap(RequestMethod::DELETE, $module, $controller); |
|
203
|
|
|
} |
|
204
|
|
|
|
|
205
|
|
|
/** |
|
206
|
|
|
* Add mapping for OPTIONS method |
|
207
|
|
|
* |
|
208
|
|
|
* @param string $module |
|
209
|
|
|
* @param string $controller |
|
210
|
|
|
* @return Link |
|
211
|
|
|
*/ |
|
212
|
|
|
public function options($module, $controller) : Link |
|
213
|
|
|
{ |
|
214
|
|
|
return $this->addMap(RequestMethod::OPTIONS, $module, $controller); |
|
215
|
16 |
|
} |
|
216
|
|
|
|
|
217
|
16 |
|
/** |
|
218
|
16 |
|
* Run |
|
219
|
|
|
* |
|
220
|
|
|
* @return Controller |
|
221
|
|
|
* @throws ControllerException |
|
222
|
|
|
* @throws ForbiddenException |
|
223
|
|
|
* @throws NotImplementedException |
|
224
|
|
|
*/ |
|
225
|
|
|
public function run() : Controller |
|
226
|
16 |
|
{ |
|
227
|
|
|
$this->prepareRequest(); |
|
228
|
|
|
return $this->dispatch(); |
|
229
|
16 |
|
} |
|
230
|
16 |
|
|
|
231
|
|
|
/** |
|
232
|
|
|
* Prepare request for processing |
|
233
|
|
|
* |
|
234
|
16 |
|
* @throws \Bluz\Controller\ControllerException |
|
235
|
|
|
*/ |
|
236
|
16 |
|
protected function prepareRequest() |
|
237
|
|
|
{ |
|
238
|
|
|
// HTTP method |
|
239
|
16 |
|
$method = Request::getMethod(); |
|
240
|
|
|
$this->method = strtoupper($method); |
|
241
|
|
|
|
|
242
|
16 |
|
// get path |
|
243
|
|
|
// %module% / %controller% / %id% / %relation% / %id% |
|
244
|
16 |
|
$path = Router::getCleanUri(); |
|
245
|
|
|
|
|
246
|
16 |
|
$this->params = explode('/', rtrim($path, '/')); |
|
247
|
|
|
|
|
248
|
16 |
|
// module |
|
249
|
|
|
$this->module = array_shift($this->params); |
|
250
|
16 |
|
|
|
251
|
16 |
|
// controller |
|
252
|
16 |
|
$this->controller = array_shift($this->params); |
|
253
|
|
|
|
|
254
|
|
|
$data = Request::getParams(); |
|
255
|
|
|
|
|
256
|
|
|
unset($data['_method'], $data['_module'], $data['_controller']); |
|
257
|
|
|
|
|
258
|
|
|
$this->data = array_merge($data, $this->data); |
|
259
|
|
|
// var_dump($this->data); |
|
|
|
|
|
|
260
|
|
|
|
|
261
|
|
|
$primary = $this->crud->getPrimaryKey(); |
|
262
|
|
|
$this->primary = array_intersect_key($this->data, array_flip($primary)); |
|
263
|
|
|
} |
|
264
|
|
|
|
|
265
|
|
|
/** |
|
266
|
16 |
|
* Dispatch REST or CRUD controller |
|
267
|
|
|
* |
|
268
|
|
|
* @return mixed |
|
269
|
16 |
|
* @throws ComponentException |
|
270
|
1 |
|
* @throws CommonException |
|
271
|
|
|
* @throws ControllerException |
|
272
|
|
|
* @throws ForbiddenException |
|
273
|
15 |
|
* @throws NotAllowedException |
|
274
|
|
|
* @throws NotAcceptableException |
|
275
|
|
|
* @throws NotImplementedException |
|
276
|
15 |
|
*/ |
|
277
|
2 |
|
protected function dispatch() |
|
278
|
|
|
{ |
|
279
|
|
|
// check implementation |
|
280
|
13 |
|
if (!isset($this->map[$this->method])) { |
|
281
|
|
|
throw new NotImplementedException; |
|
282
|
|
|
} |
|
283
|
13 |
|
|
|
284
|
13 |
|
$link = $this->map[$this->method]; |
|
285
|
13 |
|
|
|
286
|
13 |
|
// check permissions |
|
287
|
|
|
if (!Acl::isAllowed($this->module, $link->getAcl())) { |
|
288
|
|
|
throw new ForbiddenException; |
|
289
|
13 |
|
} |
|
290
|
|
|
|
|
291
|
|
|
$this->crud->setFields($link->getFields()); |
|
292
|
|
|
|
|
293
|
|
|
// dispatch controller |
|
294
|
|
|
$result = Application::getInstance()->dispatch( |
|
295
|
|
|
$link->getModule(), |
|
296
|
|
|
$link->getController(), |
|
297
|
|
|
$this->prepareParams() |
|
298
|
|
|
); |
|
299
|
|
|
|
|
300
|
|
|
return $result; |
|
301
|
|
|
} |
|
302
|
|
|
} |
|
303
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.