Passed
Branch master (2fae60)
by Alexander
02:32
created

WebApplicationRunner::debug()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Runner;
6
7
use App\Handler\ThrowableHandler;
8
use ErrorException;
9
use Psr\Container\ContainerInterface;
10
use Psr\Http\Message\RequestInterface;
11
use Psr\Http\Message\ResponseInterface;
12
use Psr\Http\Message\ServerRequestInterface;
13
use Throwable;
14
use Yiisoft\Config\Config;
15
use Yiisoft\Di\Container;
16
use Yiisoft\ErrorHandler\ErrorHandler;
17
use Yiisoft\ErrorHandler\Middleware\ErrorCatcher;
18
use Yiisoft\ErrorHandler\Renderer\HtmlRenderer;
19
use Yiisoft\Factory\Exception\CircularReferenceException;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Factory\Exceptio...cularReferenceException 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 Yiisoft\Factory\Exception\InvalidConfigException;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Factory\Exception\InvalidConfigException 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...
21
use Yiisoft\Factory\Exception\NotFoundException;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Factory\Exception\NotFoundException 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...
22
use Yiisoft\Factory\Exception\NotInstantiableException;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Factory\Exception\NotInstantiableException 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...
23
use Yiisoft\Http\Method;
24
use Yiisoft\Log\Logger;
25
use Yiisoft\Log\Target\File\FileTarget;
26
use Yiisoft\Yii\Event\ListenerConfigurationChecker;
27
use Yiisoft\Yii\Web\Application;
28
use Yiisoft\Yii\Web\Exception\HeadersHaveBeenSentException;
29
use Yiisoft\Yii\Web\SapiEmitter;
30
use Yiisoft\Yii\Web\ServerRequestFactory;
31
32
use function dirname;
33
use function microtime;
34
35
final class WebApplicationRunner
36
{
37
    private bool $debug = false;
38
39 2
    public function debug(bool $enable = true): void
40
    {
41 2
        $this->debug = $enable;
42 2
    }
43
44
    /**
45
     * @throws CircularReferenceException|ErrorException|HeadersHaveBeenSentException|InvalidConfigException
46
     * @throws NotFoundException|NotInstantiableException|
47
     */
48 2
    public function run(): void
49
    {
50 2
        $startTime = microtime(true);
51
52
        // Register temporary error handler to catch error while container is building.
53 2
        $errorHandler = $this->createTemporaryErrorHandler();
54 2
        $this->registerErrorHandler($errorHandler);
55
56 2
        $config = new Config(
57 2
            dirname(__DIR__, 2),
58 2
            '/config/packages', // Configs path.
59 2
            null,
60
            [
61 2
                'params',
62
                'events',
63
                'events-web',
64
                'events-console',
65
            ],
66
        );
67
68 2
        $container = new Container($config->get('web'), $config->get('providers-web'));
69
70
        // Register error handler with real container-configured dependencies.
71 2
        $this->registerErrorHandler($container->get(ErrorHandler::class), $errorHandler);
72
73
        // Run bootstrap
74 2
        $this->runBootstrap($container, $config->get('bootstrap-web'));
75
76 2
        $container = $container->get(ContainerInterface::class);
77
78 2
        if ($this->debug) {
79
            /** @psalm-suppress MixedMethodCall */
80 2
            $container->get(ListenerConfigurationChecker::class)->check($config->get('events-web'));
81
        }
82
83
        /** @var Application */
84 2
        $application = $container->get(Application::class);
85
86
        /**
87
         * @var ServerRequestInterface
88
         * @psalm-suppress MixedMethodCall
89
         */
90 2
        $serverRequest = $container->get(ServerRequestFactory::class)->createFromGlobals();
91 2
        $request = $serverRequest->withAttribute('applicationStartTime', $startTime);
92
93
        try {
94 2
            $application->start();
95 2
            $response = $application->handle($request);
96 2
            $this->emit($request, $response);
97
        } catch (Throwable $throwable) {
98
            $handler = new ThrowableHandler($throwable);
99
            /**
100
             * @var ResponseInterface
101
             * @psalm-suppress MixedMethodCall
102
             */
103
            $response = $container->get(ErrorCatcher::class)->process($request, $handler);
104
            $this->emit($request, $response);
105 2
        } finally {
106 2
            $application->afterEmit($response ?? null);
107 2
            $application->shutdown();
108
        }
109 2
    }
110
111 2
    private function createTemporaryErrorHandler(): ErrorHandler
112
    {
113 2
        $logger = new Logger([new FileTarget(dirname(__DIR__) . '/runtime/logs/app.log')]);
114 2
        return new ErrorHandler($logger, new HtmlRenderer());
115
    }
116
117
    /**
118
     * @throws HeadersHaveBeenSentException
119
     */
120 2
    private function emit(RequestInterface $request, ResponseInterface $response): void
121
    {
122 2
        (new SapiEmitter())->emit($response, $request->getMethod() === Method::HEAD);
123 2
    }
124
125
    /**
126
     * @throws ErrorException
127
     */
128 2
    private function registerErrorHandler(ErrorHandler $registered, ErrorHandler $unregistered = null): void
129
    {
130 2
        if ($unregistered !== null) {
131 2
            $unregistered->unregister();
132
        }
133
134 2
        if ($this->debug) {
135 2
            $registered->debug();
136
        }
137
138 2
        $registered->register();
139 2
    }
140
141 2
    private function runBootstrap(Container $container, array $bootstrapList): void
142
    {
143 2
        (new BootstrapRunner($container, $bootstrapList))->run();
144 2
    }
145
}
146