Valkyrja::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Valkyrja Framework package.
7
 *
8
 * (c) Melech Mizrachi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Valkyrja\Application;
15
16
use Override;
0 ignored issues
show
Bug introduced by
The type Override 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 Valkyrja\Application\Constant\ComponentClass;
0 ignored issues
show
Bug introduced by
The type Valkyrja\Application\Constant\ComponentClass 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...
18
use Valkyrja\Application\Contract\Application;
0 ignored issues
show
Bug introduced by
The type Valkyrja\Application\Contract\Application 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...
19
use Valkyrja\Application\Exception\RuntimeException;
20
use Valkyrja\Application\Support\Component;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Valkyrja\Application\Component. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
21
use Valkyrja\Cli\Routing\Data as CliData;
22
use Valkyrja\Container\Contract\Container;
23
use Valkyrja\Container\Data as ContainerData;
24
use Valkyrja\Event\Data as EventData;
25
use Valkyrja\Http\Routing\Data as HttpData;
26
27
/**
28
 * Class Valkyrja.
29
 *
30
 * @author Melech Mizrachi
31
 */
32
class Valkyrja implements Application
33
{
34
    /**
35
     * Application env.
36
     */
37
    protected Env $env;
0 ignored issues
show
Bug introduced by
The type Valkyrja\Application\Env 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...
38
39
    /**
40
     * Application config.
41
     */
42
    protected Config|null $config = null;
43
44
    /**
45
     * Application data.
46
     */
47
    protected Data|null $data = null;
48
49
    /**
50
     * Get the instance of the container.
51
     */
52
    protected Container $container;
53
54
    /**
55
     * Whether the application was setup.
56
     */
57
    protected bool $setup = false;
58
59
    /**
60
     * Application constructor.
61
     */
62
    public function __construct(Env $env, Config|Data $configData = new Config())
63
    {
64
        $this->setup(env: $env, configData: $configData);
65
    }
66
67
    /**
68
     * @inheritDoc
69
     */
70
    #[Override]
71
    public function setup(Env $env, Config|Data $configData = new Config(), bool $force = false): void
72
    {
73
        // If the application was already setup, no need to do it again
74
        if ($this->setup && ! $force) {
75
            return;
76
        }
77
78
        // Avoid re-setting up the app later
79
        $this->setup = true;
80
81
        $this->setEnv(env: $env);
82
83
        $this->bootstrapContainer();
84
85
        if ($configData instanceof Config) {
86
            $this->bootstrapConfig(config: $configData);
87
        } else {
88
            $this->bootstrapData(data: $configData);
89
        }
90
91
        $this->bootstrapServices();
92
    }
93
94
    /**
95
     * @inheritDoc
96
     */
97
    #[Override]
98
    public function addComponent(string $component): void
99
    {
100
        if ($this->config === null) {
101
            throw new RuntimeException('Cannot add components to an app setup with Data');
102
        }
103
104
        $this->config->aliases = [
105
            ...$this->config->aliases,
106
            ...$component::getContainerAliases(),
107
        ];
108
109
        $this->config->services = [
110
            ...$this->config->services,
111
            ...$component::getContainerServices(),
112
        ];
113
114
        array_map(
115
            [$this->container, 'register'],
116
            $component::getContainerProviders(),
117
        );
118
119
        $this->config->listeners = [
120
            ...$this->config->listeners,
121
            ...$component::getEventListeners(),
122
        ];
123
124
        $this->config->commands = [
125
            ...$this->config->commands,
126
            ...$component::getCliControllers(),
127
        ];
128
129
        $this->config->controllers = [
130
            ...$this->config->controllers,
131
            ...$component::getHttpControllers(),
132
        ];
133
    }
134
135
    /**
136
     * @inheritDoc
137
     *
138
     * @return Env
139
     */
140
    #[Override]
141
    public function getEnv(): Env
142
    {
143
        return $this->env;
144
    }
145
146
    /**
147
     * @inheritDoc
148
     */
149
    #[Override]
150
    public function setEnv(Env $env): void
151
    {
152
        // Set the env class to use
153
        $this->env = $env;
154
155
        $this->bootstrapTimezone();
156
    }
157
158
    /**
159
     * @inheritDoc
160
     */
161
    #[Override]
162
    public function getContainer(): Container
163
    {
164
        return $this->container;
165
    }
166
167
    /**
168
     * @inheritDoc
169
     */
170
    #[Override]
171
    public function setContainer(Container $container): static
172
    {
173
        $this->container = $container;
174
175
        return $this;
176
    }
177
178
    /**
179
     * @inheritDoc
180
     */
181
    #[Override]
182
    public function getDebugMode(): bool
183
    {
184
        /** @var bool $debugMode */
185
        $debugMode = $this->env::APP_DEBUG_MODE;
186
187
        return $debugMode;
188
    }
189
190
    /**
191
     * @inheritDoc
192
     */
193
    #[Override]
194
    public function getEnvironment(): string
195
    {
196
        /** @var non-empty-string $env */
197
        $env = $this->env::APP_ENV;
198
199
        return $env;
200
    }
201
202
    /**
203
     * @inheritDoc
204
     */
205
    #[Override]
206
    public function getVersion(): string
207
    {
208
        /** @var non-empty-string $version */
209
        $version = $this->env::APP_VERSION;
210
211
        return $version;
212
    }
213
214
    /**
215
     * Bootstrap the config.
216
     */
217
    protected function bootstrapConfig(Config $config): void
218
    {
219
        $this->config = $config;
220
221
        $this->bootstrapComponents();
222
    }
223
224
    /**
225
     * Bootstrap all the components set in the config.
226
     */
227
    protected function bootstrapComponents(): void
228
    {
229
        // All all the components
230
        $this->addComponent(component: ComponentClass::CONTAINER);
231
        $this->addComponent(component: ComponentClass::APPLICATION);
232
        $this->addComponent(component: ComponentClass::ATTRIBUTE);
233
        $this->addComponent(component: ComponentClass::CLI);
234
        $this->addComponent(component: ComponentClass::DISPATCHER);
235
        $this->addComponent(component: ComponentClass::EVENT);
236
        $this->addComponent(component: ComponentClass::HTTP);
237
        $this->addComponent(component: ComponentClass::REFLECTION);
238
239
        /** @var class-string<Component>[] $components */
240
        $components = $this->env::APP_COMPONENTS;
241
242
        foreach ($components as $component) {
243
            $this->addComponent(component: $component);
244
        }
245
    }
246
247
    /**
248
     * Bootstrap the data.
249
     */
250
    protected function bootstrapData(Data $data): void
251
    {
252
        $this->data = $data;
253
    }
254
255
    /**
256
     * Create the container.
257
     */
258
    protected function bootstrapContainer(): void
259
    {
260
        $container = new \Valkyrja\Container\Container();
261
262
        $this->setContainer($container);
263
    }
264
265
    /**
266
     * Bootstrap container services.
267
     */
268
    protected function bootstrapServices(): void
269
    {
270
        $container = $this->container;
271
272
        $container->setSingleton(Application::class, $this);
273
        $container->setSingleton(Env::class, $this->env);
274
        $container->setSingleton(Container::class, $container);
275
276
        if ($this->data !== null) {
277
            $container->setSingleton(ContainerData::class, $this->data->container);
278
            $container->setSingleton(EventData::class, $this->data->event);
279
            $container->setSingleton(CliData::class, $this->data->cli);
280
            $container->setSingleton(HttpData::class, $this->data->http);
281
282
            $container->setFromData($this->data->container);
283
        }
284
285
        if ($this->config !== null) {
286
            $container->setSingleton(Config::class, $this->config);
287
288
            $data = $container->getSingleton(ContainerData::class);
289
            $container->setFromData($data);
290
        }
291
    }
292
293
    /**
294
     * Bootstrap the timezone.
295
     */
296
    protected function bootstrapTimezone(): void
297
    {
298
        /** @var non-empty-string $timezone */
299
        $timezone = $this->env::APP_TIMEZONE;
300
301
        date_default_timezone_set($timezone);
302
    }
303
}
304