Completed
Push — master ( 6f2bb4...6400d0 )
by Anton
11s
created

Meta::getPrivilege()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
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;
12
13
use Bluz\Common\Exception\ComponentException;
14
use Bluz\Common\Options;
15
use Bluz\Proxy\Request;
16
17
/**
18
 * Meta information from reflection of the function
19
 *
20
 * @package  Bluz\Controller
21
 * @author   Anton Shevchuk
22
 */
23
class Meta
24
{
25
    use Options;
26
27
    /**
28
     * @var string full path to file
29
     */
30
    protected $file;
31
32
    /**
33
     * @var integer cache TTL
34
     */
35
    protected $cache = 0;
36
37
    /**
38
     * @var array list of Accept
39
     */
40
    protected $accept = [];
41
42
    /**
43
     * @var array list of Acl
44
     */
45
    protected $acl = [];
46
47
    /**
48
     * @var array list of HTTP methods
49
     */
50
    protected $method = [];
51
52
    /**
53
     * @var array described params
54
     */
55
    protected $params = [];
56
57
    /**
58
     * @var string privilege
59
     */
60
    protected $privilege;
61
62
    /**
63
     * @var array routers
64
     */
65
    protected $route = [];
66
67
    /**
68
     * @var array default values of params
69
     */
70
    protected $values = [];
71
72
    /**
73
     * Constructor of Reflection
74
     *
75
     * @param string $file
76
     */
77 587
    public function __construct($file)
78
    {
79 587
        $this->file = $file;
80 587
    }
81
82
    /**
83
     * Set state required for working with var_export (used inside PHP File cache)
84
     *
85
     * @param  array $array
86
     *
87
     * @return Meta
88
     */
89
    public static function __set_state($array)
90
    {
91
        $instance = new Meta($array['file']);
92
        foreach ($array as $key => $value) {
93
            $instance->{$key} = $value;
94
        }
95
        return $instance;
96
    }
97
98
    /**
99
     * Process to get reflection from file
100
     *
101
     * @return void
102
     * @throws ComponentException
103
     */
104 587
    public function process() : void
105
    {
106
        /** @var \Closure|object $closure */
107 587
        $closure = include $this->file;
108
109 587
        if (!is_callable($closure)) {
110 1
            throw new ComponentException("There is no callable structure in file `{$this->file}`");
111
        }
112
113 587
        $reflection = new \ReflectionFunction($closure);
114
115
        // check and normalize params by doc comment
116 587
        $docComment = $reflection->getDocComment();
117
118
        // get all options by one regular expression
119 587
        if (preg_match_all('/\s*\*\s*\@([a-z0-9-_]+)\s+(.*).*\s+/i', $docComment, $matches)) {
120 587
            foreach ($matches[1] as $i => $key) {
121 587
                $this->setOption($key, trim($matches[2][$i]));
122
            }
123
        }
124
125
        // init routes
126 587
        $this->initRoute();
127
128
        // get params and convert it to simple array
129 587
        $reflectionParams = $reflection->getParameters();
130
        // setup params and optional params
131 587
        foreach ($reflectionParams as $param) {
132 587
            $name = $param->getName();
133
            // if some function params is missed in description
134 587
            if (!isset($this->params[$name])) {
135 587
                $this->params[$name] = null;
136
            }
137 587
            if ($param->isOptional()) {
138 587
                $this->values[$name] = $param->getDefaultValue();
139
            }
140
        }
141 587
    }
142
143
    /**
144
     * Process request params
145
     *
146
     *  - type conversion
147
     *  - set default value
148
     *
149
     * @param  array $requestParams
150
     *
151
     * @return array
152
     */
153 40
    public function params($requestParams) : array
154
    {
155
        // apply type and default value for request params
156 40
        $params = [];
157 40
        foreach ($this->params as $param => $type) {
158 6
            if (isset($requestParams[$param])) {
159 6
                switch ($type) {
160 3
                    case 'bool':
161 3
                    case 'boolean':
162
                        $params[] = (bool)$requestParams[$param];
163
                        break;
164 3
                    case 'int':
165 3
                    case 'integer':
166 3
                        $params[] = (int)$requestParams[$param];
167 3
                        break;
168 3
                    case 'float':
169
                        $params[] = (float)$requestParams[$param];
170
                        break;
171 3
                    case 'string':
172
                        $params[] = (string)$requestParams[$param];
173
                        break;
174 3
                    case 'array':
175
                        $params[] = (array)$requestParams[$param];
176
                        break;
177
                    default:
178 6
                        $params[] = $requestParams[$param];
179 6
                        break;
180
                }
181 2
            } elseif (isset($this->values[$param])) {
182
                $params[] = $this->values[$param];
183
            } else {
184 6
                $params[] = null;
185
            }
186
        }
187 40
        return $params;
188
    }
189
190
    /**
191
     * Get path to file
192
     *
193
     * @return string
194
     */
195
    public function getFile() : string
196
    {
197
        return $this->file;
198
    }
199
200
    /**
201
     * Get Cache TTL
202
     *
203
     * @return integer
204
     */
205 41
    public function getCache() : int
206
    {
207 41
        return $this->cache;
208
    }
209
210
    /**
211
     * Set Cache TTL
212
     *
213
     * @param  string $ttl
214
     *
215
     * @return void
216
     */
217 2
    public function setCache($ttl) : void
218
    {
219 2
        $this->cache = $this->prepareCache($ttl);
220 2
    }
221
222
    /**
223
     * Prepare Cache
224
     *
225
     * @param  string $cache
226
     *
227
     * @return integer
228
     */
229 2
    protected function prepareCache($cache) : int
230
    {
231 2
        $num = (int)$cache;
232 2
        $time = 'min';
233
234 2
        if ($pos = strpos($cache, ' ')) {
235 2
            $time = substr($cache, $pos);
236
        }
237
238 2
        switch ($time) {
239
            case 'day':
240
            case 'days':
241
                return $num * 86400;
242
            case 'hour':
243
            case 'hours':
244
                return $num * 3600;
245
            case 'min':
246
            default:
247 2
                return $num * 60;
248
        }
249
    }
250
251
    /**
252
     * Get accepted type
253
     *
254
     * @return array|null
255
     */
256 40
    public function getAccept() : ?array
257
    {
258 40
        return count($this->accept) ? $this->accept : null;
259
    }
260
261
    /**
262
     * Set accepted types
263
     *
264
     * @param  string $accept
265
     *
266
     * @return void
267
     */
268
    public function setAccept($accept) : void
269
    {
270
        // allow accept map
271
        $acceptMap = [
272
            'ANY' => Request::TYPE_ANY,
273
            'HTML' => Request::TYPE_HTML,
274
            'JSON' => Request::TYPE_JSON
275
        ];
276
277
        $accept = strtoupper($accept);
278
279
        if (isset($acceptMap[$accept])) {
280
            $this->accept[] = $acceptMap[$accept];
281
        }
282
    }
283
284
    /**
285
     * Get Acl privileges
286
     *
287
     * @return array|null
288
     */
289 1
    public function getAcl() : ?array
290
    {
291 1
        return count($this->acl) ? $this->acl : null;
292
    }
293
294
    /**
295
     * Set Acl privileges
296
     *
297
     * @param  string $acl
298
     *
299
     * @return void
300
     */
301 2
    public function setAcl($acl) : void
302
    {
303 2
        $this->acl[] = $acl;
304 2
    }
305
306
    /**
307
     * Get HTTP Method
308
     *
309
     * @return array|null
310
     */
311 41
    public function getMethod() : ?array
312
    {
313 41
        return count($this->method) ? $this->method : null;
314
    }
315
316
    /**
317
     * Set HTTP Method
318
     *
319
     * @param  string $method
320
     *
321
     * @return void
322
     */
323 2
    public function setMethod($method) : void
324
    {
325 2
        $this->method[] = strtoupper($method);
326 2
    }
327
328
    /**
329
     * Get all params
330
     *
331
     * @return array
332
     */
333 587
    public function getParams() : array
334
    {
335 587
        return $this->params;
336
    }
337
338
    /**
339
     * Set param types
340
     *
341
     * @param  string $param
342
     *
343
     * @return void
344
     */
345 587
    public function setParam($param) : void
346
    {
347
        // prepare params data
348
        // setup param types
349 587
        if (strpos($param, '$') === false) {
350
            return;
351
        }
352
353 587
        [$type, $key] = preg_split('/[ $]+/', $param);
354
355 587
        $this->params[$key] = trim($type);
356 587
    }
357
358
    /**
359
     * Get Privilege fo ACL
360
     *
361
     * @return string|null
362
     */
363 41
    public function getPrivilege() : ?string
364
    {
365 41
        return $this->privilege;
366
    }
367
368
    /**
369
     * Set Privilege fo ACL allow only one privilege
370
     *
371
     * @param  string $privilege
372
     *
373
     * @return void
374
     */
375 2
    public function setPrivilege($privilege) : void
376
    {
377 2
        $this->privilege = $privilege;
378 2
    }
379
380
    /**
381
     * Get Route
382
     *
383
     * @return array|null
384
     */
385 587
    public function getRoute() : ?array
386
    {
387 587
        return count($this->route) ? $this->route : null;
388
    }
389
390
    /**
391
     * Set Route
392
     *
393
     * @param  string $route
394
     *
395
     * @return void
396
     */
397 587
    public function setRoute($route) : void
398
    {
399 587
        $this->route[$route] = null;
400 587
    }
401
402
    /**
403
     * Init Route
404
     *
405
     * @return void
406
     */
407 587
    protected function initRoute() : void
408
    {
409 587
        foreach ($this->route as $route => &$pattern) {
410 587
            $pattern = $this->prepareRoutePattern($route);
411
        }
412 587
    }
413
414
    /**
415
     * Prepare Route pattern
416
     *
417
     * @param  string $route
418
     *
419
     * @return string
420
     */
421 587
    protected function prepareRoutePattern($route): string
422
    {
423 587
        $pattern = str_replace('/', '\/', $route);
424
425 587
        foreach ($this->getParams() as $param => $type) {
426 587
            switch ($type) {
427
                case 'int':
428
                case 'integer':
429 587
                    $pattern = str_replace("{\$$param}", "(?P<$param>[0-9]+)", $pattern);
430 587
                    break;
431
                case 'float':
432 587
                    $pattern = str_replace("{\$$param}", "(?P<$param>[0-9.,]+)", $pattern);
433 587
                    break;
434
                case 'string':
435
                case 'module':
436
                case 'controller':
437 587
                    $pattern = str_replace(
438 587
                        "{\$$param}",
439 587
                        "(?P<$param>[a-zA-Z0-9-_.]+)",
440 587
                        $pattern
441
                    );
442 587
                    break;
443
            }
444
        }
445 587
        return '/^' . $pattern . '/i';
446
    }
447
}
448