TKernel::getContainer()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Nymfonya\Component\Http\Reuse;
6
7
use Monolog\Logger;
8
use Nymfonya\Component\Config;
9
use Nymfonya\Component\Container;
10
use Nymfonya\Component\Pubsub\Dispatcher;
11
use Nymfonya\Component\Http\Kernel;
12
use Nymfonya\Component\Http\Middleware;
13
use Nymfonya\Component\Http\Request;
14
use Nymfonya\Component\Http\Response;
15
use Nymfonya\Component\Http\Router;
16
use ReflectionClass;
17
18
trait TKernel
19
{
20
21
    /**
22
     * app path
23
     *
24
     * @var string
25
     */
26
    protected $path;
27
28
    /**
29
     * app environment
30
     *
31
     * @var string
32
     */
33
    protected $env;
34
35
    /**
36
     * app config
37
     *
38
     * @var Config
39
     */
40
    protected $config;
41
42
    /**
43
     * service container
44
     *
45
     * @var Container
46
     */
47
    protected $container;
48
49
    /**
50
     * monolog logger
51
     *
52
     * @var Logger
53
     */
54
    protected $logger;
55
56
    /**
57
     * app request
58
     *
59
     * @var Request
60
     */
61
    protected $req;
62
63
    /**
64
     * app response
65
     *
66
     * @var Response
67
     */
68
    protected $res;
69
70
    /**
71
     * app router
72
     *
73
     * @var Router
74
     */
75
    protected $router;
76
77
    /**
78
     * app dispatcher
79
     *
80
     * @var Dispatcher
81
     */
82
    protected $dispatcher;
83
84
    /**
85
     * ctrl class name
86
     *
87
     * @var string
88
     */
89
    protected $className;
90
91
    /**
92
     * controller namespace
93
     *
94
     * @var string
95
     */
96
    protected $spacename;
97
98
    /**
99
     * controller instance
100
     *
101
     * @var mixed
102
     */
103
    protected $controller;
104
105
    /**
106
     * reflection class instance
107
     *
108
     * @var ReflectionClass
109
     */
110
    protected $reflector;
111
112
    /**
113
     * controller actions
114
     *
115
     * @var array
116
     */
117
    protected $actions;
118
119
    /**
120
     * controller action
121
     *
122
     * @var string
123
     */
124
    protected $action;
125
126
    /**
127
     * action annotations
128
     *
129
     * @var string
130
     */
131
    protected $actionAnnotations;
132
133
    /**
134
     * middlewares stack
135
     *
136
     * @var array
137
     */
138
    protected $middlewares;
139
140
    /**
141
     * run error
142
     *
143
     * @var Boolean
144
     */
145
    protected $error;
146
147
    /**
148
     * http status error code
149
     *
150
     * @var int
151
     */
152
    protected $errorCode;
153
154
    /**
155
     * error message
156
     *
157
     * @var string
158
     */
159
    protected $errorMsg;
160
161
    /**
162
     * return service container for service name
163
     *
164
     * @param string $serviceName
165
     * @throws Exception
166
     * @return object
167
     */
168 28
    public function getService(string $serviceName)
169
    {
170 28
        return $this->container->getService($serviceName);
171
    }
172
173
    /**
174
     * init kernel
175
     *
176
     * @param string $env
177
     * @param string $path
178
     * @return void
179
     */
180 2
    protected function init(string $env, string $path)
181
    {
182 2
        $this->env = $env;
183 2
        $this->path = $path;
184 2
        $this->error = true;
185 2
        $this->errorCode = Response::HTTP_NOT_FOUND;
186 2
        $this->errorMsg = 'Not Found';
187 2
        $this->setPath($path);
188 2
        $this->setConfig();
189 2
        $this->setContainer();
190 2
        $this->setDispatcher();
0 ignored issues
show
Bug introduced by
It seems like setDispatcher() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

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