Completed
Push — master ( 7cb220...404236 )
by Anton
10s
created

Meta::getAccept()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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