Passed
Pull Request — master (#310)
by Melech
01:25
created

App::getContainer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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\Entry;
15
16
use Valkyrja\Application\Data\Config;
17
use Valkyrja\Application\Data\Data;
18
use Valkyrja\Application\Env\Env;
0 ignored issues
show
Bug introduced by
The type Valkyrja\Application\Env\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...
19
use Valkyrja\Application\Kernel\Contract\ApplicationContract;
0 ignored issues
show
Bug introduced by
The type Valkyrja\Application\Ker...act\ApplicationContract 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...
20
use Valkyrja\Application\Kernel\Valkyrja;
21
use Valkyrja\Application\Throwable\Exception\RuntimeException;
22
use Valkyrja\Cli\Interaction\Factory\InputFactory;
23
use Valkyrja\Cli\Interaction\Input\Contract\InputContract;
24
use Valkyrja\Cli\Server\Handler\Contract\InputHandlerContract;
25
use Valkyrja\Container\Manager\Container;
26
use Valkyrja\Container\Manager\Contract\ContainerContract;
27
use Valkyrja\Http\Message\Factory\RequestFactory;
28
use Valkyrja\Http\Message\Request\Contract\ServerRequestContract;
29
use Valkyrja\Http\Server\Handler\Contract\RequestHandlerContract;
30
use Valkyrja\Support\Directory\Directory;
0 ignored issues
show
Bug introduced by
The type Valkyrja\Support\Directory\Directory 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...
31
use Valkyrja\Support\Time\Microtime;
32
use Valkyrja\Throwable\Handler\Contract\ThrowableHandlerContract;
33
use Valkyrja\Throwable\Handler\WhoopsThrowableHandler;
34
35
use function define;
36
use function defined;
37
38
class App
39
{
40
    /**
41
     * Start the application.
42
     *
43
     * @param non-empty-string $dir The directory
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
44
     */
45
    public static function start(string $dir, Env $env): ApplicationContract
46
    {
47
        static::defaultExceptionHandler();
48
        static::appStart();
49
        static::directory(dir: $dir);
50
51
        return static::app(env: $env);
52
    }
53
54
    /**
55
     * Now that the application has been bootstrapped and setup correctly with all our requirements lets run it!
56
     *
57
     * @param non-empty-string $dir The directory
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
58
     */
59
    public static function http(string $dir, Env $env): void
60
    {
61
        $app = static::start(
62
            dir: $dir,
63
            env: $env,
64
        );
65
66
        $container = $app->getContainer();
67
68
        self::bootstrapThrowableHandler($app, $container);
69
70
        $handler = $container->getSingleton(RequestHandlerContract::class);
71
        $request = static::getRequest();
72
        $handler->run($request);
73
    }
74
75
    /**
76
     * Now that the application has been bootstrapped and setup correctly with all our requirements lets run it!
77
     *
78
     * @param non-empty-string $dir The directory
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
79
     */
80
    public static function cli(string $dir, Env $env): void
81
    {
82
        $app = static::start(
83
            dir: $dir,
84
            env: $env,
85
        );
86
87
        $container = $app->getContainer();
88
89
        self::bootstrapThrowableHandler($app, $container);
90
91
        $handler = $container->getSingleton(InputHandlerContract::class);
92
        $input   = static::getInput();
93
        $handler->run($input);
94
    }
95
96
    /**
97
     * Set a global constant for when the application as a whole started.
98
     */
99
    public static function appStart(): void
100
    {
101
        if (! defined('APP_START')) {
102
            define('APP_START', Microtime::get());
103
        }
104
    }
105
106
    /**
107
     * Let's set the base directory within the web server for our application
108
     * so that when we locate directories and files within the application
109
     * we have a standard location from which to do so.
110
     *
111
     * @param non-empty-string $dir The directory
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
112
     */
113
    public static function directory(string $dir): void
114
    {
115
        Directory::$BASE_PATH = $dir;
116
    }
117
118
    /**
119
     * Let's start up the application by creating a new instance of the
120
     * application class. This is going to bind all the various
121
     * components together into a singular hub. This will set the
122
     *  correct environment class file to use, and appropriate the config
123
     *  that should be loaded by the application. In dev you'll want to
124
     *  use the default config out of the root config directory, but
125
     *  when you're on a production environment definitely have
126
     *  your config cached and the flag set in your env class.
127
     */
128
    public static function app(Env $env): ApplicationContract
129
    {
130
        /** @var non-empty-string $cacheFilepath */
131
        $cacheFilepath = $env::APP_CACHE_FILE_PATH;
132
        $cacheFilename = Directory::basePath($cacheFilepath);
133
134
        if (is_file(filename: $cacheFilename)) {
135
            $configData = static::getData(cacheFilename: $cacheFilename);
136
        } else {
137
            $configData = static::getConfig();
138
        }
139
140
        $container = static::getContainer();
141
142
        return new Valkyrja(
143
            container: $container,
144
            env: $env,
145
            configData: $configData
146
        );
147
    }
148
149
    /**
150
     * Get the application config.
151
     */
152
    protected static function getConfig(): Config
153
    {
154
        return new Config();
155
    }
156
157
    /**
158
     * Get the application data.
159
     *
160
     * @param non-empty-string $cacheFilename The cache file path
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
161
     */
162
    protected static function getData(string $cacheFilename): Data
163
    {
164
        $cache = file_get_contents(filename: $cacheFilename);
165
166
        if ($cache === false || $cache === '') {
167
            throw new RuntimeException('Error occurred when retrieving cache file contents');
168
        }
169
170
        // Allow all classes, and filter for only Data classes down below since allowed_classes cannot be
171
        // a class that others extend off of, and we don't want to limit what a cached data class could be
172
        $data = unserialize($cache, ['allowed_classes' => true]);
173
174
        if (! $data instanceof Data) {
175
            throw new RuntimeException('Invalid cache');
176
        }
177
178
        return $data;
179
    }
180
181
    /**
182
     * Set a default exception handler until the one specified in config is set in the Container\AppProvider.
183
     */
184
    protected static function defaultExceptionHandler(): void
185
    {
186
        WhoopsThrowableHandler::enable(
187
            displayErrors: true
188
        );
189
    }
190
191
    /**
192
     * Bootstrap throwable handler.
193
     */
194
    protected static function bootstrapThrowableHandler(ApplicationContract $app, ContainerContract $container): void
195
    {
196
        $errorHandler = static::getThrowableHandler();
197
198
        // Set error handler in the service container
199
        $container->setSingleton(ThrowableHandlerContract::class, $errorHandler);
200
201
        // If debug is on, enable debug handling
202
        if ($app->getDebugMode()) {
203
            // Enable error handling
204
            $errorHandler::enable(
205
                displayErrors: true
206
            );
207
        }
208
    }
209
210
    /**
211
     * Get the throwable handler.
212
     */
213
    protected static function getThrowableHandler(): ThrowableHandlerContract
214
    {
215
        return new WhoopsThrowableHandler();
216
    }
217
218
    /**
219
     * Get the container.
220
     */
221
    protected static function getContainer(): ContainerContract
222
    {
223
        return new Container();
224
    }
225
226
    /**
227
     * Get the request.
228
     */
229
    protected static function getRequest(): ServerRequestContract
230
    {
231
        return RequestFactory::fromGlobals();
232
    }
233
234
    /**
235
     * Get the input.
236
     */
237
    protected static function getInput(): InputContract
238
    {
239
        return InputFactory::fromGlobals();
240
    }
241
}
242