Passed
Push — master ( c2bb1d...64c4d2 )
by Paweł
02:06
created

Kernel::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
c 4
b 0
f 0
nc 1
nop 1
dl 0
loc 11
rs 9.9666
1
<?php
2
3
namespace pjpawel\LightApi;
4
5
use Exception;
6
use pjpawel\LightApi\Command\CommandsLoader;
7
use pjpawel\LightApi\Component\ClassWalker;
8
use pjpawel\LightApi\Component\Env;
9
use pjpawel\LightApi\Component\Event\EventHandler;
10
use pjpawel\LightApi\Container\ContainerLoader;
11
use pjpawel\LightApi\Route\Router;
12
use pjpawel\LightApi\Http\Request;
13
use pjpawel\LightApi\Http\Response;
14
use Psr\Log\LoggerInterface;
15
use Symfony\Component\Cache\Adapter\AbstractAdapter;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Cache\Adapter\AbstractAdapter was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
17
class Kernel
18
{
19
20
    public const VERSION = 003000;
21
    public const VERSION_DOTTED = '0.3.0';
22
    /* only for stable version */
23
    //public const VERSION_END_OF_LIFE = '06/2023';
24
    //public const VERSION_END_OF_MAINTENANCE = '03/2023';
25
26
    public const KERNEL_CACHE_NAME = 'kernel.cache';
27
    public const KERNEL_LOGGER_NAME = 'kernel.logger';
28
    private const PROPERTIES_TO_CACHE = [
29
        'containerLoader' => 'kernel.container',
30
        'router' => 'kernel.router',
31
        'commandLoader' => 'kernel.command'
32
    ];
33
34
    /**
35
     * @var string project directory
36
     */
37
    public string $projectDir;
38
    public string $env;
39
    public bool $debug;
40
    private Router $router;
41
    private CommandsLoader $commandLoader;
42
    private ContainerLoader $containerLoader;
43
    private ?LoggerInterface $kernelLogger;
44
    private EventHandler $eventHandler;
45
    private AbstractAdapter $kernelCache;
46
47
    public function __construct(string $configDir)
48
    {
49
        $env = new Env();
50
        $config = $env->getConfigFromEnv($configDir);
51
        $this->projectDir = $config['projectDir'];
52
        $this->env = $config['env'];
53
        $this->debug = $config['debug'];
54
        $this->kernelCache = $env->createClassFromConfig($config['cache']);
55
        $this->boot($config);
56
        $this->ensureContainerHasKernelServices();
57
        $this->eventHandler->tryTriggering(EventHandler::KERNEL_AFTER_BOOT);
58
    }
59
60
    protected function boot(array $config): void
61
    {
62
        $loaded = false;
63
        if (!$this->debug) {
64
            $loaded = true;
65
            foreach (self::PROPERTIES_TO_CACHE as $property => $cacheName) {
66
                $routerItem = $this->kernelCache->getItem($cacheName);
67
                if (!$routerItem->isHit()) {
68
                    $loaded = false;
69
                    break;
70
                }
71
                $this->$property = $routerItem->get();
72
            }
73
        }
74
        if (!$loaded) {
75
            $classWalker = new ClassWalker($config['services'] ?? $this->projectDir);
76
            $this->containerLoader = new ContainerLoader();
77
            $this->router = new Router();
78
            $this->commandLoader = new CommandsLoader();
79
            $classWalker->register($this->containerLoader, $this->router, $this->commandLoader);
80
            $this->containerLoader->createDefinitionsFromConfig($config['container']);
81
        }
82
    }
83
84
    private function ensureContainerHasKernelServices(): void
85
    {
86
        if (!$this->containerLoader->has(EventHandler::class)) {
87
            $this->containerLoader->add(['name' => EventHandler::class]);
88
            $this->eventHandler = $this->containerLoader->get(EventHandler::class);
89
        }
90
        $this->containerLoader->add(['name' => self::KERNEL_CACHE_NAME, 'object' => $this->kernelCache]);
91
        if ($this->containerLoader->has(self::KERNEL_LOGGER_NAME)) {
92
            $this->kernelLogger = $this->containerLoader->get(self::KERNEL_LOGGER_NAME);
93
        } else {
94
            $this->kernelLogger = null;
95
        }
96
    }
97
98
    /**
99
     * @param Request $request
100
     * @return Response
101
     * @throws Exception
102
     */
103
    public function handleRequest(Request $request): Response
104
    {
105
        $request->logRequest($this->kernelLogger);
106
        $request->validateIp();
107
        $this->eventHandler->tryTriggering(EventHandler::KERNEL_BEFORE_REQUEST);
108
        try {
109
            $route = $this->router->getRoute($request);
110
        } catch (Exception $e) {
111
            return $this->router->getErrorResponse($e);
112
        }
113
        $this->containerLoader->add(['name' => Request::class, 'args' => [], 'object' => $request]);
114
        $response = $route->execute($this->containerLoader, $request);
115
        $this->eventHandler->tryTriggering(EventHandler::KERNEL_AFTER_REQUEST);
116
        return $response;
117
    }
118
119
    /**
120
     * @param string|null $commandName
121
     * @return int
122
     */
123
    public function handleCommand(?string $commandName = null): int
124
    {
125
        if ($commandName === null) {
126
            $commandName = $this->commandLoader->getCommandNameFromServer();
127
        }
128
        $this->eventHandler->tryTriggering(EventHandler::KERNEL_BEFORE_COMMAND);
129
        if (str_starts_with($commandName, 'kernel:')) {
130
            return $this->commandLoader->runCommandFromName($commandName, $this->containerLoader, $this);
131
        }
132
        $code = $this->commandLoader->runCommandFromName($commandName, $this->containerLoader);
133
        $this->eventHandler->tryTriggering(EventHandler::KERNEL_AFTER_COMMAND);
134
        return $code;
135
    }
136
137
    public function __destruct()
138
    {
139
        $this->eventHandler->tryTriggering(EventHandler::KERNEL_ON_DESTRUCT);
140
        if (!$this->debug) {
141
            foreach (self::PROPERTIES_TO_CACHE as $property => $cacheName) {
142
                $cacheItem = $this->kernelCache->getItem($cacheName);
143
                $cacheItem->set($this->$property);
144
            }
145
        }
146
    }
147
}