Completed
Pull Request — master (#443)
by Anton
05:12
created

AbstractMapper::dispatch()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 0
dl 0
loc 25
ccs 12
cts 12
cp 1
crap 3
rs 8.8571
c 0
b 0
f 0
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 25
    public function __construct(AbstractCrud $crud)
106
    {
107 25
        $this->crud = $crud;
108 25
    }
109
110
    /**
111
     * Add mapping data
112
     *
113
     * @param string $method
114
     * @param string $module
115
     * @param string $controller
116
     * @return Link
117
     */
118 24
    public function addMap($method, $module, $controller) : Link
119
    {
120 24
        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 1
    public function head($module, $controller) : Link
141
    {
142 1
        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 1
    public function get($module, $controller) : Link
153
    {
154 1
        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 1
    public function post($module, $controller) : Link
165
    {
166 1
        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 1
    public function patch($module, $controller) : Link
177
    {
178 1
        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 1
    public function put($module, $controller) : Link
189
    {
190 1
        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 1
    public function delete($module, $controller) : Link
201
    {
202 1
        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 1
    public function options($module, $controller) : Link
213
    {
214 1
        return $this->addMap(RequestMethod::OPTIONS, $module, $controller);
215
    }
216
217
    /**
218
     * Run
219
     *
220
     * @return Controller
221
     * @throws ControllerException
222
     * @throws ForbiddenException
223
     * @throws NotImplementedException
224
     */
225 25
    public function run() : Controller
226
    {
227 25
        $this->prepareRequest();
228 25
        return $this->dispatch();
229
    }
230
231
    /**
232
     * Prepare request for processing
233
     *
234
     * @throws \Bluz\Controller\ControllerException
235
     */
236 25
    protected function prepareRequest()
237
    {
238
        // HTTP method
239 25
        $method = Request::getMethod();
240 25
        $this->method = strtoupper($method);
241
242
        // get path
243
        // %module% / %controller% / %id% / %relation% / %id%
244 25
        $path = Router::getCleanUri();
245
246 25
        $this->params = explode('/', rtrim($path, '/'));
247
248
        // module
249 25
        $this->module = array_shift($this->params);
250
251
        // controller
252 25
        $this->controller = array_shift($this->params);
253
254 25
        $data = Request::getParams();
255
256 25
        unset($data['_method'], $data['_module'], $data['_controller']);
257
258 25
        $this->data = array_merge($data, $this->data);
259
260 25
        $primary = $this->crud->getPrimaryKey();
261 25
        $this->primary = array_intersect_key($this->data, array_flip($primary));
262 25
    }
263
264
    /**
265
     * Dispatch REST or CRUD controller
266
     *
267
     * @return mixed
268
     * @throws ComponentException
269
     * @throws CommonException
270
     * @throws ControllerException
271
     * @throws ForbiddenException
272
     * @throws NotAllowedException
273
     * @throws NotAcceptableException
274
     * @throws NotImplementedException
275
     */
276 25
    protected function dispatch()
277
    {
278
        // check implementation
279 25
        if (!isset($this->map[$this->method])) {
280 1
            throw new NotImplementedException;
281
        }
282
283 24
        $link = $this->map[$this->method];
284
285
        // check permissions
286 24
        if (!Acl::isAllowed($this->module, $link->getAcl())) {
287 2
            throw new ForbiddenException;
288
        }
289
290 22
        $this->crud->setFields($link->getFields());
291
292
        // dispatch controller
293 22
        $result = Application::getInstance()->dispatch(
294 22
            $link->getModule(),
295 22
            $link->getController(),
296 22
            $this->prepareParams()
297
        );
298
299 22
        return $result;
300
    }
301
}
302