Completed
Push — master ( e58d71...c7fb50 )
by Pierre
06:50
created

TKernel::execute()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 6

Importance

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

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
560
    {
561 5
        return $this->error;
562
    }
563
564
    /**
565
     * return kernel error message
566
     *
567
     */
568 3
    protected function getErrorMsg(): string
569
    {
570 3
        return $this->errorMsg;
571
    }
572
}
573