Completed
Push — master ( 3cf2a3...b96e1a )
by Pierre
02:31 queued 12s
created

TKernel::setAction()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 3
rs 10
1
<?php
2
3
namespace App\Reuse;
4
5
use App\Kernel;
6
use App\Config;
7
use App\Container;
8
use App\Http\Request;
9
use App\Http\Response;
10
use App\Http\Router;
11
use App\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 $nameSpace;
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 26
    public function getService(string $serviceName)
159
    {
160 26
        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 2
    protected function init(string $env, string $path)
171
    {
172 2
        $this->env = $env;
173 2
        $this->path = $path;
174 2
        $this->error = true;
175 2
        $this->errorCode = Response::HTTP_NOT_FOUND;
176 2
        $this->errorMsg = 'Not Found';
177 2
        $this->setPath($path);
178 2
        $this->setConfig();
179 2
        $this->setContainer();
180 2
        $this->setRequest();
181 2
        $this->setResponse();
182 2
        $this->setLogger();
183 2
        $this->setRouter();
184 2
        $this->className = '';
185 2
        $this->actions = [];
186 2
        $this->action = '';
187 2
        $this->actionAnnotations = '';
188
    }
189
190
    /**
191
     * execute controller action in middleware core closure
192
     *
193
     * @return void
194
     */
195 3
    protected function execute(...$args)
196
    {
197 3
        if ($this->isValidAction() && is_object($this->controller)) {
198 2
            $resExec = $this->invokeAction($args);
199 2
            $this->error = ($resExec === false);
200 2
            $this->errorCode = ($this->error)
201 1
                ? Response::HTTP_INTERNAL_SERVER_ERROR
202 1
                : Response::HTTP_OK;
203 2
            $this->errorMsg = sprintf(
204 2
                'Execute %s',
205 2
                ($this->error) ? 'failed' : 'successfully'
206
            );
207 2
            $this->logger->debug($this->errorMsg);
208
        } else {
209 1
            $this->error = true;
210 1
            $this->errorMsg = 'Unknown endpoint';
211 1
            $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 1
    protected function invokeAction(...$args)
223
    {
224 1
        return call_user_func_array([$this->controller, $this->action], $args);
225
    }
226
227
    /**
228
     * return controller instance
229
     *
230
     * @return mixed
231
     */
232 3
    protected function getController()
233
    {
234 3
        return $this->controller;
235
    }
236
237
    /**
238
     * set middlewares from config then run before/after layers around core
239
     *
240
     */
241 1
    protected function setMiddleware()
242
    {
243 1
        $middlwaresConfig = $this->config->getSettings(
244 1
            Config::_MIDDLEWARES
245
        );
246 1
        $middlwaresClasses = array_keys($middlwaresConfig);
247 1
        foreach ($middlwaresClasses as $className) {
248 1
            $this->middlewares[$className] = new $className;
249
        }
250 1
        (new Middleware())->layer($this->middlewares)->peel(
251 1
            $this->container,
252 1
            function ($container) {
253 1
                $this->execute(null);
254 1
                return $container;
255 1
            }
256
        );
257
    }
258
259
    /**
260
     * set action annotations for runnig action
261
     *
262
     */
263 1
    protected function setActionAnnotations()
264
    {
265 1
        if ($this->isValidAction()) {
266 1
            $refMethod = $this->reflector->getMethod($this->action);
267 1
            $docComment = $refMethod->getDocComment();
268 1
            $noComment = (false === $refMethod || false === $docComment);
269 1
            $this->actionAnnotations = ($noComment)
270
                ? ''
271 1
                : (string) $docComment;
272 1
            unset($refMethod, $docComment, $noComment);
273
        }
274
    }
275
276
    /**
277
     * return action docblock as string
278
     *
279
     * @return string
280
     */
281 1
    protected function getActionAnnotations(): string
282
    {
283 1
        return $this->actionAnnotations;
284
    }
285
286
    /**
287
     * return true if action is valid
288
     *
289
     * @return boolean
290
     */
291 5
    protected function isValidAction(): bool
292
    {
293 5
        return in_array($this->action, $this->actions);
294
    }
295
296
    /**
297
     * instanciate controller for a classname
298
     *
299
     * @return void
300
     */
301 4
    protected function setController()
302
    {
303 4
        $this->controller = new $this->className($this->container);
304
    }
305
306
    /**
307
     * set relflector on class name
308
     *
309
     */
310 8
    protected function setReflector()
311
    {
312 8
        $this->reflector = new \ReflectionClass($this->className);
313
    }
314
315
    /**
316
     * return reflexion class on current classname
317
     *
318
     * @return ReflectionClass
319
     */
320 1
    protected function getReflector(): ReflectionClass
321
    {
322 1
        return $this->reflector;
323
    }
324
325
    /**
326
     * return core controller action
327
     *
328
     * @return string
329
     */
330 1
    protected function getAction(): string
331
    {
332 1
        return $this->action;
333
    }
334
335
    /**
336
     * set public final actions from controller class name
337
     *
338
     */
339 8
    protected function setActions()
340
    {
341 8
        $methods = $this->getFinalMethods();
342 8
        $methodsName = array_map(function ($method) {
343 8
            return $method->name;
344 8
        }, $methods);
345 8
        $this->actions = array_merge($methodsName, ['preflight']);
346
    }
347
348
    /**
349
     * get final methods for the current classname
350
     *
351
     * @return array
352
     */
353 1
    protected function getFinalMethods(): array
354
    {
355 1
        return $this->getReflector()->getMethods(
356 1
            \ReflectionMethod::IS_FINAL
357
        );
358
    }
359
360
    /**
361
     * return public final actions from controller class name
362
     *
363
     */
364 4
    protected function getActions(): array
365
    {
366 4
        return $this->actions;
367
    }
368
369
    /**
370
     * set service container
371
     *
372
     */
373 1
    protected function setContainer()
374
    {
375 1
        $this->container = new \App\Container(
376 1
            $this->config->getSettings(Config::_SERVICES)
377
        );
378 1
        $this->container->setService(\App\Kernel::class, $this);
379
    }
380
381
    /**
382
     * get service container
383
     *
384
     */
385 2
    protected function getContainer(): Container
386
    {
387 2
        return $this->container;
388
    }
389
390
    /**
391
     * set request
392
     *
393
     */
394 1
    protected function setRequest()
395
    {
396 1
        $this->req = $this->getService(\App\Http\Request::class);
397
    }
398
399
    /**
400
     * return request
401
     *
402
     */
403 1
    protected function getRequest(): Request
404
    {
405 1
        return $this->req;
406
    }
407
408
    /**
409
     * set response
410
     *
411
     */
412 1
    protected function setResponse()
413
    {
414 1
        $this->res = $this->getService(\App\Http\Response::class);
415
    }
416
417
    /**
418
     * return reponse
419
     *
420
     */
421 1
    protected function getResponse(): Response
422
    {
423 1
        return $this->res;
424
    }
425
426
    /**
427
     * set router
428
     *
429
     */
430 1
    protected function setRouter()
431
    {
432 1
        $this->router = $this->getService(\App\Http\Router::class);
433
    }
434
435
    /**
436
     * return router
437
     *
438
     */
439 1
    protected function getRouter(): Router
440
    {
441 1
        return $this->router;
442
    }
443
444
    /**
445
     * set controller class name
446
     *
447
     * @param array $routerGroups
448
     */
449 8
    protected function setClassname(array $routerGroups)
450
    {
451 8
        $this->className = $this->nameSpace
452 8
            . implode(
453 8
            '\\',
454 8
            array_map('ucfirst', explode('/', $routerGroups[0]))
455
        );
456
    }
457
458
    /**
459
     * set controller class name
460
     *
461
     */
462 4
    protected function getClassname(): string
463
    {
464 4
        return $this->className;
465
    }
466
467
    /**
468
     * set app config
469
     *
470
     */
471 1
    protected function setConfig()
472
    {
473 1
        $this->config = new Config(
474 1
            $this->env,
475 1
            $this->path . Kernel::PATH_CONFIG
476
        );
477
    }
478
479
    /**
480
     * returns config
481
     *
482
     * @return Config
483
     */
484 1
    protected function getConfig(): Config
485
    {
486 1
        return $this->config;
487
    }
488
489
    /**
490
     * set app logger
491
     *
492
     */
493 1
    protected function setLogger()
494
    {
495 1
        $this->logger = $this->getService(\Monolog\Logger::class);
496 1
        $handlers = $this->logger->getHandlers();
497 1
        foreach ($handlers as $handlder) {
498 1
            if ($handlder instanceof \Monolog\Handler\RotatingFileHandler) {
499 1
                $patchedHandlder = $handlder;
500 1
                $patchedHandlder->setFilenameFormat(
501 1
                    '{date}-{filename}',
502 1
                    'Y-m-d'
503
                );
504 1
                $this->logger->popHandler();
505 1
                $this->logger->pushHandler($patchedHandlder);
506
            }
507
        }
508 1
        unset($handlers);
509
        //\Monolog\ErrorHandler::register($this->logger);
510
    }
511
512
    /**
513
     * return monolog logger with handlers set
514
     *
515
     * @return Logger
516
     */
517 2
    public function getLogger(): Logger
518
    {
519 2
        return $this->logger;
520
    }
521
522
    /**
523
     * set app root path
524
     *
525
     */
526 1
    protected function setPath(string $path)
527
    {
528 1
        $this->path = $path;
529
    }
530
531
    /**
532
     * return kernel run path
533
     *
534
     * @return string
535
     */
536 2
    protected function getPath(): string
537
    {
538 2
        return $this->path;
539
    }
540
541
    /**
542
     * set kernel error
543
     *
544
     */
545 2
    protected function setError(bool $error)
546
    {
547 2
        $this->error = $error;
548
    }
549
550
    /**
551
     * return kernel error
552
     *
553
     */
554 5
    protected function getError(): bool
555
    {
556 5
        return $this->error;
557
    }
558
559
    /**
560
     * return kernel error message
561
     *
562
     */
563 3
    protected function getErrorMsg(): string
564
    {
565 3
        return $this->errorMsg;
566
    }
567
}
568