Completed
Push — master ( 3cc38b...18691f )
by Pierre
03:50
created

TKernel::getClassname()   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\Reuse;
4
5
use App\Kernel;
6
use App\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 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' : 'success'
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($this->router->getParams());
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
            $this->actionAnnotations = '';
267 1
            $refMethod = $this->reflector->getMethod($this->action);
268 1
            $docComment = $refMethod->getDocComment();
269 1
            $noComment = (false === $refMethod || false === $docComment);
270 1
            if (false === $noComment) {
271 1
                $this->actionAnnotations = (string) $docComment;
272
            }
273 1
            unset($refMethod, $docComment, $noComment);
274
        }
275
    }
276
277
    /**
278
     * return action docblock as string
279
     *
280
     * @return string
281
     */
282 1
    protected function getActionAnnotations(): string
283
    {
284 1
        return $this->actionAnnotations;
285
    }
286
287
    /**
288
     * return true if action is valid
289
     *
290
     * @return boolean
291
     */
292 5
    protected function isValidAction(): bool
293
    {
294 5
        return in_array($this->action, $this->actions);
295
    }
296
297
    /**
298
     * instanciate controller for a classname
299
     *
300
     * @return void
301
     */
302 4
    protected function setController()
303
    {
304 4
        $this->controller = new $this->className($this->container);
305
    }
306
307
    /**
308
     * set relflector on class name
309
     *
310
     */
311 8
    protected function setReflector()
312
    {
313 8
        $this->reflector = new \ReflectionClass($this->className);
314
    }
315
316
    /**
317
     * return reflexion class on current classname
318
     *
319
     * @return ReflectionClass
320
     */
321 1
    protected function getReflector(): ReflectionClass
322
    {
323 1
        return $this->reflector;
324
    }
325
326
    /**
327
     * return core controller action
328
     *
329
     * @return string
330
     */
331 1
    protected function getAction(): string
332
    {
333 1
        return $this->action;
334
    }
335
336
    /**
337
     * set public final actions from controller class name
338
     *
339
     */
340 8
    protected function setActions()
341
    {
342 8
        $methods = $this->getFinalMethods();
343 8
        $methodsName = array_map(function ($method) {
344 8
            return $method->name;
345 8
        }, $methods);
346 8
        $this->actions = array_merge($methodsName, ['preflight']);
347
    }
348
349
    /**
350
     * get final methods for the current classname
351
     *
352
     * @return array
353
     */
354 1
    protected function getFinalMethods(): array
355
    {
356 1
        return $this->getReflector()->getMethods(
357 1
            \ReflectionMethod::IS_FINAL
358
        );
359
    }
360
361
    /**
362
     * return public final actions from controller class name
363
     *
364
     */
365 4
    protected function getActions(): array
366
    {
367 4
        return $this->actions;
368
    }
369
370
    /**
371
     * set service container
372
     *
373
     */
374 1
    protected function setContainer()
375
    {
376 1
        $this->container = new Container(
377 1
            $this->config->getSettings(Config::_SERVICES)
378
        );
379 1
        $this->container->setService(\App\Kernel::class, $this);
380
    }
381
382
    /**
383
     * get service container
384
     *
385
     */
386 2
    protected function getContainer(): Container
387
    {
388 2
        return $this->container;
389
    }
390
391
    /**
392
     * set request
393
     *
394
     */
395 1
    protected function setRequest()
396
    {
397 1
        $this->req = $this->getService(Request::class);
398
    }
399
400
    /**
401
     * return request
402
     *
403
     */
404 1
    protected function getRequest(): Request
405
    {
406 1
        return $this->req;
407
    }
408
409
    /**
410
     * set response
411
     *
412
     */
413 1
    protected function setResponse()
414
    {
415 1
        $this->res = $this->getService(Response::class);
416
    }
417
418
    /**
419
     * return reponse
420
     *
421
     */
422 1
    protected function getResponse(): Response
423
    {
424 1
        return $this->res;
425
    }
426
427
    /**
428
     * set router
429
     *
430
     */
431 1
    protected function setRouter()
432
    {
433 1
        $this->router = $this->getService(Router::class);
434
    }
435
436
    /**
437
     * return router
438
     *
439
     */
440 1
    protected function getRouter(): Router
441
    {
442 1
        return $this->router;
443
    }
444
445
    /**
446
     * set controller class name
447
     *
448
     * @param array $routerGroups
449
     */
450 8
    protected function setClassname(array $routerGroups)
451
    {
452 8
        $this->className = $this->spacename
453 8
            . implode(
454 8
                '\\',
455 8
                array_map('ucfirst', explode('/', $routerGroups[0]))
456
            );
457
    }
458
459
    /**
460
     * set controller class name
461
     *
462
     */
463 4
    protected function getClassname(): string
464
    {
465 4
        return $this->className;
466
    }
467
468
    /**
469
     * set app config
470
     *
471
     */
472 1
    protected function setConfig()
473
    {
474 1
        $this->config = new Config(
475 1
            $this->env,
476 1
            $this->path . Kernel::PATH_CONFIG
477
        );
478
    }
479
480
    /**
481
     * returns config
482
     *
483
     * @return Config
484
     */
485 1
    protected function getConfig(): Config
486
    {
487 1
        return $this->config;
488
    }
489
490
    /**
491
     * set app logger
492
     *
493
     */
494 1
    protected function setLogger()
495
    {
496 1
        $this->logger = $this->getService(\Monolog\Logger::class);
497 1
        $handlers = $this->logger->getHandlers();
498 1
        foreach ($handlers as $handlder) {
499 1
            if ($handlder instanceof \Monolog\Handler\RotatingFileHandler) {
500 1
                $patchedHandlder = $handlder;
501 1
                $patchedHandlder->setFilenameFormat(
502 1
                    '{date}-{filename}',
503 1
                    'Y-m-d'
504
                );
505 1
                $this->logger->popHandler();
506 1
                $this->logger->pushHandler($patchedHandlder);
507
            }
508
        }
509 1
        unset($handlers);
510
        //\Monolog\ErrorHandler::register($this->logger);
511
    }
512
513
    /**
514
     * return monolog logger with handlers set
515
     *
516
     * @return Logger
517
     */
518 2
    public function getLogger(): Logger
519
    {
520 2
        return $this->logger;
521
    }
522
523
    /**
524
     * set app root path
525
     *
526
     */
527 1
    protected function setPath(string $path)
528
    {
529 1
        $this->path = $path;
530
    }
531
532
    /**
533
     * return kernel run path
534
     *
535
     * @return string
536
     */
537 2
    protected function getPath(): string
538
    {
539 2
        return $this->path;
540
    }
541
542
    /**
543
     * set kernel error
544
     *
545
     */
546 2
    protected function setError(bool $error)
547
    {
548 2
        $this->error = $error;
549
    }
550
551
    /**
552
     * return kernel error
553
     *
554
     */
555 5
    protected function getError(): bool
556
    {
557 5
        return $this->error;
558
    }
559
560
    /**
561
     * return kernel error message
562
     *
563
     */
564 3
    protected function getErrorMsg(): string
565
    {
566 3
        return $this->errorMsg;
567
    }
568
}
569