Passed
Branch master (a91c94)
by Stanislau
22:03 queued 19:22
created

AppKernel::kernel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 0
dl 0
loc 19
ccs 8
cts 8
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 *  This file is part of the Micro framework package.
5
 *
6
 *  (c) Stanislau Komar <[email protected]>
7
 *
8
 *  For the full copyright and license information, please view the LICENSE
9
 *  file that was distributed with this source code.
10
 */
11
12
namespace Micro\Kernel\App;
13
14
use Micro\Component\DependencyInjection\Container;
15
use Micro\Framework\Kernel\Boot\ConfigurationProviderBootLoader;
16
use Micro\Framework\Kernel\Boot\DependedPluginsBootLoader;
0 ignored issues
show
Bug introduced by
The type Micro\Framework\Kernel\B...pendedPluginsBootLoader 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...
17
use Micro\Framework\Kernel\Boot\DependencyProviderBootLoader;
18
use Micro\Framework\Kernel\Configuration\ApplicationConfigurationInterface;
19
use Micro\Framework\Kernel\KernelBuilder;
20
use Micro\Framework\Kernel\KernelInterface;
21
use Micro\Framework\Kernel\Plugin\PluginBootLoaderInterface;
22
use Micro\Kernel\App\Business\KernelActionProcessorInterface;
23
use Micro\Kernel\App\Business\KernelRunActionProcessor;
24
use Micro\Kernel\App\Business\KernelTerminateActionProcessor;
25
use Micro\Plugin\EventEmitter\EventEmitterPlugin;
26
use Micro\Plugin\Locator\LocatorPlugin;
27
28
class AppKernel implements AppKernelInterface
29
{
30
    private bool $isTerminated;
31
32
    private bool $isStarted;
33
34
    private ?KernelInterface $kernel;
35
36
    /**
37
     * @var PluginBootLoaderInterface[]
38
     */
39
    private array $additionalBootLoaders = [];
40
41
    /**
42
     * @param ApplicationConfigurationInterface|array<string, string> $configuration
43
     * @param class-string[]                                          $plugins
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string[] at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string[].
Loading history...
44
     */
45 11
    public function __construct(
46
        private readonly ApplicationConfigurationInterface|array $configuration = [],
47
        private array $plugins = [],
48
        private readonly string $environment = 'dev'
49
    ) {
50 11
        $this->kernel = null;
51 11
        $this->isTerminated = false;
52 11
        $this->isStarted = false;
53
    }
54
55
    /**
56
     * {@inheritDoc}
57
     */
58 8
    public function container(): Container
59
    {
60 8
        return $this->kernel()->container();
61
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66 9
    public function plugins(string $interfaceInherited = null): \Traversable
67
    {
68 9
        return $this->kernel()->plugins($interfaceInherited);
69
    }
70
71
    /**
72
     * {@inheritDoc}
73
     */
74 9
    public function run(): void
75
    {
76 9
        if ($this->isStarted) {
77 1
            return;
78
        }
79
80 9
        $this->kernel = $this->createKernel();
81
82 9
        $this->kernel->run();
0 ignored issues
show
Bug introduced by
The method run() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

82
        $this->kernel->/** @scrutinizer ignore-call */ 
83
                       run();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
83
84 9
        $this->createInitActionProcessor()->process($this);
85
86 9
        $this->isStarted = true;
87
    }
88
89
    /**
90
     * {@inheritDoc}
91
     */
92 2
    public function terminate(): void
93
    {
94 2
        if ($this->isTerminated || !$this->isStarted) {
95 1
            return;
96
        }
97
98 2
        $this->createTerminateActionProcessor()->process($this);
99
100 2
        $this->isTerminated = true;
101
    }
102
103
    /**
104
     * {@inheritDoc}
105
     */
106 8
    public function environment(): string
107
    {
108 8
        return $this->environment;
109
    }
110
111
    /**
112
     * {@inheritDoc}
113
     */
114 6
    public function isDevMode(): bool
115
    {
116 6
        return str_starts_with($this->environment(), 'dev');
117
    }
118
119
    /**
120
     * {@inheritDoc}
121
     */
122 1
    public function addBootLoader(PluginBootLoaderInterface $bootLoader): self
123
    {
124 1
        $this->additionalBootLoaders[] = $bootLoader;
125
126 1
        return $this;
127
    }
128
129
    /**
130
     * {@inheritDoc}
131
     */
132 1
    public function loadPlugin(string $applicationPluginClass): void
133
    {
134 1
        $this->kernel()->loadPlugin($applicationPluginClass);
135
    }
136
137 9
    protected function createKernel(): KernelInterface
138
    {
139 9
        $container = new Container();
140 9
        $plugins = $this->plugins;
141 9
        $this->plugins = [];
142
143 9
        return $this
144 9
            ->createKernelBuilder()
145 9
            ->setContainer($container)
146 9
            ->addBootLoaders($this->createBootLoaderCollection($container))
147 9
            ->setApplicationPlugins(array_unique([
148 9
                    EventEmitterPlugin::class,
149 9
                    LocatorPlugin::class,
150 9
                    ...$plugins,
151 9
                ])
152 9
            )
153 9
            ->build();
154
    }
155
156 9
    protected function kernel(): KernelInterface
157
    {
158 9
        if (!$this->kernel) {
159 1
            $trace = debug_backtrace();
160 1
            $caller = $trace[1];
161
            /**
162
             * @var string $cc
163
             *
164
             * @phpstan-ignore-next-line
165
             *
166
             * @psalm-suppress PossiblyUndefinedArrayOffset
167
             */
168 1
            $cc = $caller['class'];
169 1
            $cm = $caller['function'];
170
171 1
            throw new \RuntimeException(sprintf('Method %s::%s can not be called before %s::run() execution.', $cc, $cm, KernelInterface::class));
172
        }
173
174 8
        return $this->kernel;
175
    }
176
177 9
    protected function createKernelBuilder(): KernelBuilder
178
    {
179 9
        return new KernelBuilder();
180
    }
181
182 8
    protected function createInitActionProcessor(): KernelActionProcessorInterface
183
    {
184 8
        return new KernelRunActionProcessor();
185
    }
186
187 1
    protected function createTerminateActionProcessor(): KernelActionProcessorInterface
188
    {
189 1
        return new KernelTerminateActionProcessor();
190
    }
191
192
    /**
193
     * @return PluginBootLoaderInterface[]
194
     */
195 8
    protected function createBootLoaderCollection(Container $container): array
196
    {
197 8
        $bl = $this->additionalBootLoaders;
198
199 8
        $this->additionalBootLoaders = [];
200
201 8
        return [
0 ignored issues
show
Bug Best Practice introduced by
The expression return array(new Micro\F...BootLoader($this), $bl) returns an array which contains values of type array which are incompatible with the documented value type Micro\Framework\Kernel\P...uginBootLoaderInterface.
Loading history...
202 8
            new ConfigurationProviderBootLoader($this->configuration),
203 8
            new DependencyProviderBootLoader($container),
204 8
            new DependedPluginsBootLoader($this),
205 8
            ...$bl,
206 8
        ];
207
    }
208
209
    public function setBootLoaders(iterable $bootLoaders): KernelInterface
210
    {
211
        $this->kernel()->setBootLoaders($bootLoaders);
212
213
        return $this;
214
    }
215
}
216