Completed
Push — master ( 14c33c...acb33b )
by Pierre
03:53
created

TKernel::isValidAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace App\Component\Http\Reuse;
4
5
use App\Component\Http\Kernel;
6
use App\Component\Config;
7
use App\Component\Container;
8
use App\Component\Http\Request;
9
use App\Component\Http\Response;
10
use App\Component\Http\Router;
11
use App\Component\Http\Middleware;
12
use Monolog\Logger;
13
use \ReflectionClass;
14
15
trait TKernel
16
{
17
18
    /**
19
     * app path
20
     *
21
     * @var string
22
     */
23
    protected $path;
24
25
    /**
26
     * app environment
27
     *
28
     * @var string
29
     */
30
    protected $env;
31
32
    /**
33
     * app config
34
     *
35
     * @var Config
36
     */
37
    protected $config;
38
39
    /**
40
     * service container
41
     *
42
     * @var Container
43
     */
44
    protected $container;
45
46
    /**
47
     * monolog logger
48
     *
49
     * @var Logger
50
     */
51
    protected $logger;
52
53
    /**
54
     * app request
55
     *
56
     * @var Request
57
     */
58
    protected $req;
59
60
    /**
61
     * app response
62
     *
63
     * @var Response
64
     */
65
    protected $res;
66
67
    /**
68
     * app router
69
     *
70
     * @var Router
71
     */
72
    protected $router;
73
74
    /**
75
     * ctrl class name
76
     *
77
     * @var string
78
     */
79
    protected $className;
80
81
    /**
82
     * controller namespace
83
     *
84
     * @var string
85
     */
86
    protected $spacename;
87
88
    /**
89
     * controller instance
90
     *
91
     * @var mixed
92
     */
93
    protected $controller;
94
95
    /**
96
     * reflection class instance
97
     *
98
     * @var ReflectionClass
99
     */
100
    protected $reflector;
101
102
    /**
103
     * controller actions
104
     *
105
     * @var array
106
     */
107
    protected $actions;
108
109
    /**
110
     * controller action
111
     *
112
     * @var string
113
     */
114
    protected $action;
115
116
    /**
117
     * action annotations
118
     *
119
     * @var string
120
     */
121
    protected $actionAnnotations;
122
123
    /**
124
     * middlewares stack
125
     *
126
     * @var array
127
     */
128
    protected $middlewares;
129
130
    /**
131
     * run error
132
     *
133
     * @var Boolean
134
     */
135
    protected $error;
136
137
    /**
138
     * http status error code
139
     *
140
     * @var int
141
     */
142
    protected $errorCode;
143
144
    /**
145
     * error message
146
     *
147
     * @var string
148
     */
149
    protected $errorMsg;
150
151
    /**
152
     * return service container for service name
153
     *
154
     * @param string $serviceName
155
     * @throws Exception
156
     * @return object
157
     */
158 52
    public function getService(string $serviceName)
159
    {
160 52
        return $this->container->getService($serviceName);
161
    }
162
163
    /**
164
     * init kernel
165
     *
166
     * @param string $env
167
     * @param string $path
168
     * @return void
169
     */
170 4
    protected function init(string $env, string $path)
171
    {
172 4
        $this->env = $env;
173 4
        $this->path = $path;
174 4
        $this->error = true;
175 4
        $this->errorCode = Response::HTTP_NOT_FOUND;
176 4
        $this->errorMsg = 'Not Found';
177 4
        $this->setPath($path);
178 4
        $this->setConfig();
179 4
        $this->setContainer();
180 4
        $this->setRequest();
181 4
        $this->setResponse();
182 4
        $this->setLogger();
183 4
        $this->setRouter();
184 4
        $this->className = '';
185 4
        $this->actions = [];
186 4
        $this->action = '';
187 4
        $this->actionAnnotations = '';
188
    }
189
190
    /**
191
     * execute controller action in middleware core closure
192
     *
193
     * @return void
194
     */
195 6
    protected function execute(...$args)
196
    {
197 6
        if ($this->isValidAction() && is_object($this->controller)) {
198 4
            $resExec = $this->invokeAction($args);
199 4
            $this->error = ($resExec === false);
200 4
            $this->errorCode = ($this->error)
201 2
                ? Response::HTTP_INTERNAL_SERVER_ERROR
202 2
                : Response::HTTP_OK;
203 4
            $this->errorMsg = sprintf(
204 4
                'Execute %s',
205 4
                ($this->error) ? 'failed' : 'success'
206
            );
207 4
            $this->logger->debug($this->errorMsg);
208
        } else {
209 2
            $this->error = true;
210 2
            $this->errorMsg = 'Unknown endpoint';
211 2
            $this->errorCode = Response::HTTP_BAD_REQUEST;
212
        }
213
    }
214
215
    /**
216
     * invoke action from a controller an return exec code.
217
     * for testing purpose return retValue if false
218
     *
219
     * @param boolean $forceRetValue
220
     * @return mixed
221
     */
222 2
    protected function invokeAction(...$args)
223
    {
224 2
        return call_user_func_array([$this->controller, $this->action], $args);
225
    }
226
227
    /**
228
     * return controller instance
229
     *
230
     * @return mixed
231
     */
232 6
    protected function getController()
233
    {
234 6
        return $this->controller;
235
    }
236
237
    /**
238
     * set middlewares from config then run before/after layers around core
239
     *
240
     */
241 2
    protected function setMiddleware()
242
    {
243 2
        $middlwaresConfig = $this->config->getSettings(
244 2
            Config::_MIDDLEWARES
245
        );
246 2
        $middlwaresClasses = array_keys($middlwaresConfig);
247 2
        foreach ($middlwaresClasses as $className) {
248 2
            $this->middlewares[$className] = new $className;
249
        }
250 2
        (new Middleware())->layer($this->middlewares)->peel(
251 2
            $this->container,
252 2
            function ($container) {
253 2
                $this->execute($this->router->getParams());
254 2
                return $container;
255 2
            }
256
        );
257
    }
258
259
    /**
260
     * set action annotations for runnig action
261
     *
262
     */
263 2
    protected function setActionAnnotations()
264
    {
265 2
        if ($this->isValidAction()) {
266 2
            $this->actionAnnotations = '';
267 2
            $refMethod = $this->reflector->getMethod($this->action);
268 2
            $docComment = $refMethod->getDocComment();
269 2
            $noComment = (false === $refMethod || false === $docComment);
270 2
            if (false === $noComment) {
271 2
                $this->actionAnnotations = (string) $docComment;
272
            }
273 2
            unset($refMethod, $docComment, $noComment);
274
        }
275
    }
276
277
    /**
278
     * return action docblock as string
279
     *
280
     * @return string
281
     */
282 2
    protected function getActionAnnotations(): string
283
    {
284 2
        return $this->actionAnnotations;
285
    }
286
287
    /**
288
     * return true if action is valid
289
     *
290
     * @return boolean
291
     */
292 10
    protected function isValidAction(): bool
293
    {
294 10
        return in_array($this->action, $this->actions);
295
    }
296
297
    /**
298
     * instanciate controller for a classname
299
     *
300
     * @return void
301
     */
302 8
    protected function setController()
303
    {
304 8
        $this->controller = new $this->className($this->container);
305
    }
306
307
    /**
308
     * set relflector on class name
309
     *
310
     */
311 16
    protected function setReflector()
312
    {
313 16
        $this->reflector = new \ReflectionClass($this->className);
314
    }
315
316
    /**
317
     * return reflexion class on current classname
318
     *
319
     * @return ReflectionClass
320
     */
321 2
    protected function getReflector(): ReflectionClass
322
    {
323 2
        return $this->reflector;
324
    }
325
326
    /**
327
     * return core controller action
328
     *
329
     * @return string
330
     */
331 2
    protected function getAction(): string
332
    {
333 2
        return $this->action;
334
    }
335
336
    /**
337
     * set public final actions from controller class name
338
     *
339
     */
340 16
    protected function setActions()
341
    {
342 16
        $methods = $this->getFinalMethods();
343 16
        $methodsName = array_map(function ($method) {
344 16
            return $method->name;
345 16
        }, $methods);
346 16
        $this->actions = array_merge($methodsName, ['preflight']);
347
    }
348
349
    /**
350
     * get final methods for the current classname
351
     *
352
     * @return array
353
     */
354 2
    protected function getFinalMethods(): array
355
    {
356 2
        return $this->getReflector()->getMethods(
357 2
            \ReflectionMethod::IS_FINAL
358
        );
359
    }
360
361
    /**
362
     * return public final actions from controller class name
363
     *
364
     */
365 8
    protected function getActions(): array
366
    {
367 8
        return $this->actions;
368
    }
369
370
    /**
371
     * set service container
372
     *
373
     */
374 2
    protected function setContainer()
375
    {
376 2
        $this->container = new Container(
377 2
            $this->config->getSettings(Config::_SERVICES)
378
        );
379 2
        $this->container->setService(
380 2
            \App\Component\Http\Kernel::class,
381 2
            $this
382
        );
383
    }
384
385
    /**
386
     * get service container
387
     *
388
     */
389 4
    protected function getContainer(): Container
390
    {
391 4
        return $this->container;
392
    }
393
394
    /**
395
     * set request
396
     *
397
     */
398 2
    protected function setRequest()
399
    {
400 2
        $this->req = $this->getService(Request::class);
401
    }
402
403
    /**
404
     * return request
405
     *
406
     */
407 2
    protected function getRequest(): Request
408
    {
409 2
        return $this->req;
410
    }
411
412
    /**
413
     * set response
414
     *
415
     */
416 2
    protected function setResponse()
417
    {
418 2
        $this->res = $this->getService(Response::class);
419
    }
420
421
    /**
422
     * return reponse
423
     *
424
     */
425 2
    protected function getResponse(): Response
426
    {
427 2
        return $this->res;
428
    }
429
430
    /**
431
     * set router
432
     *
433
     */
434 2
    protected function setRouter()
435
    {
436 2
        $this->router = $this->getService(Router::class);
437
    }
438
439
    /**
440
     * return router
441
     *
442
     */
443 2
    protected function getRouter(): Router
444
    {
445 2
        return $this->router;
446
    }
447
448
    /**
449
     * set controller class name
450
     *
451
     * @param array $routerGroups
452
     */
453 16
    protected function setClassname(array $routerGroups)
454
    {
455 16
        $this->className = $this->spacename
456 16
            . implode(
457 16
                '\\',
458 16
                array_map('ucfirst', explode('/', $routerGroups[0]))
459
            );
460
    }
461
462
    /**
463
     * set controller class name
464
     *
465
     */
466 8
    protected function getClassname(): string
467
    {
468 8
        return $this->className;
469
    }
470
471
    /**
472
     * set app config
473
     *
474
     */
475 2
    protected function setConfig()
476
    {
477 2
        $this->config = new Config(
478 2
            $this->env,
479 2
            $this->path . Kernel::PATH_CONFIG
480
        );
481
    }
482
483
    /**
484
     * returns config
485
     *
486
     * @return Config
487
     */
488 2
    protected function getConfig(): Config
489
    {
490 2
        return $this->config;
491
    }
492
493
    /**
494
     * set app logger
495
     *
496
     */
497 2
    protected function setLogger()
498
    {
499 2
        $this->logger = $this->getService(\Monolog\Logger::class);
500 2
        $handlers = $this->logger->getHandlers();
501 2
        foreach ($handlers as $handlder) {
502 2
            if ($handlder instanceof \Monolog\Handler\RotatingFileHandler) {
503 2
                $patchedHandlder = $handlder;
504 2
                $patchedHandlder->setFilenameFormat(
505 2
                    '{date}-{filename}',
506 2
                    'Y-m-d'
507
                );
508 2
                $this->logger->popHandler();
509 2
                $this->logger->pushHandler($patchedHandlder);
510
            }
511
        }
512 2
        unset($handlers);
513
        //\Monolog\ErrorHandler::register($this->logger);
514
    }
515
516
    /**
517
     * return monolog logger with handlers set
518
     *
519
     * @return Logger
520
     */
521 4
    public function getLogger(): Logger
522
    {
523 4
        return $this->logger;
524
    }
525
526
    /**
527
     * set app root path
528
     *
529
     */
530 2
    protected function setPath(string $path)
531
    {
532 2
        $this->path = $path;
533
    }
534
535
    /**
536
     * return kernel run path
537
     *
538
     * @return string
539
     */
540 4
    protected function getPath(): string
541
    {
542 4
        return $this->path;
543
    }
544
545
    /**
546
     * set kernel error
547
     *
548
     */
549 4
    protected function setError(bool $error)
550
    {
551 4
        $this->error = $error;
552
    }
553
554
    /**
555
     * return kernel error
556
     *
557
     */
558 10
    protected function getError(): bool
559
    {
560 10
        return $this->error;
561
    }
562
563
    /**
564
     * return kernel error message
565
     *
566
     */
567 6
    protected function getErrorMsg(): string
568
    {
569 6
        return $this->errorMsg;
570
    }
571
}
572