Passed
Push — master ( 8241e4...1bc467 )
by Alexander
03:14
created

WebApplicationRunner::run()   A

Complexity

Conditions 3
Paths 32

Size

Total Lines 66
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 3.016

Importance

Changes 0
Metric Value
eloc 35
dl 0
loc 66
ccs 29
cts 33
cp 0.8788
rs 9.36
c 0
b 0
f 0
cc 3
nc 32
nop 0
crap 3.016

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Definitions\Exception\CircularReferenceException;
16
use Yiisoft\Definitions\Exception\InvalidConfigException;
17
use Yiisoft\Definitions\Exception\NotFoundException;
18
use Yiisoft\Definitions\Exception\NotInstantiableException;
19
use Yiisoft\Di\Container;
20
use Yiisoft\ErrorHandler\ErrorHandler;
21
use Yiisoft\ErrorHandler\Middleware\ErrorCatcher;
22
use Yiisoft\ErrorHandler\Renderer\JsonRenderer;
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;
38
    private ?string $environment;
39
40 14
    public function __construct(bool $debug, ?string $environment)
41
    {
42 14
        $this->debug = $debug;
43 14
        $this->environment = $environment;
44 14
    }
45
46
    /**
47
     * @throws CircularReferenceException|ErrorException|HeadersHaveBeenSentException|InvalidConfigException
48
     * @throws NotFoundException|NotInstantiableException|
49
     */
50 14
    public function run(): void
51
    {
52 14
        $startTime = microtime(true);
53
54
        // Register temporary error handler to catch error while container is building.
55 14
        $errorHandler = $this->createTemporaryErrorHandler();
56 14
        $this->registerErrorHandler($errorHandler);
57
58 14
        $config = new Config(
59 14
            dirname(__DIR__, 2),
60 14
            '/config/packages', // Configs path.
61 14
            $this->environment,
62
            [
63 14
                'params',
64
                'events',
65
                'events-web',
66
                'events-console',
67
            ],
68
        );
69
70 14
        $container = new Container(
71 14
            $config->get('web'),
72 14
            $config->get('providers'),
73 14
            [],
74 14
            $this->debug,
75 14
            $config->get('delegates-web')
76
        );
77
78
        // Register error handler with real container-configured dependencies.
79 14
        $this->registerErrorHandler($container->get(ErrorHandler::class), $errorHandler);
80
81
        // Run bootstrap
82 14
        $this->runBootstrap($container, $config->get('bootstrap-web'));
83
84 14
        $container = $container->get(ContainerInterface::class);
85
86 14
        if ($this->debug) {
87
            /** @psalm-suppress MixedMethodCall */
88 14
            $container->get(ListenerConfigurationChecker::class)->check($config->get('events-web'));
89
        }
90
91
        /** @var Application */
92 14
        $application = $container->get(Application::class);
93
94
        /**
95
         * @var ServerRequestInterface
96
         * @psalm-suppress MixedMethodCall
97
         */
98 14
        $serverRequest = $container->get(ServerRequestFactory::class)->createFromGlobals();
99 14
        $request = $serverRequest->withAttribute('applicationStartTime', $startTime);
100
101
        try {
102 14
            $application->start();
103 14
            $response = $application->handle($request);
104 14
            $this->emit($request, $response);
105
        } catch (Throwable $throwable) {
106
            $handler = new ThrowableHandler($throwable);
107
            /**
108
             * @var ResponseInterface
109
             * @psalm-suppress MixedMethodCall
110
             */
111
            $response = $container->get(ErrorCatcher::class)->process($request, $handler);
112
            $this->emit($request, $response);
113 14
        } finally {
114 14
            $application->afterEmit($response ?? null);
115 14
            $application->shutdown();
116
        }
117 14
    }
118
119 14
    private function createTemporaryErrorHandler(): ErrorHandler
120
    {
121 14
        $logger = new Logger([new FileTarget(dirname(__DIR__) . '/runtime/logs/app.log')]);
122 14
        return new ErrorHandler($logger, new JsonRenderer());
123
    }
124
125
    /**
126
     * @throws HeadersHaveBeenSentException
127
     */
128 14
    private function emit(RequestInterface $request, ResponseInterface $response): void
129
    {
130 14
        (new SapiEmitter())->emit($response, $request->getMethod() === Method::HEAD);
131 14
    }
132
133
    /**
134
     * @throws ErrorException
135
     */
136 14
    private function registerErrorHandler(ErrorHandler $registered, ErrorHandler $unregistered = null): void
137
    {
138 14
        if ($unregistered !== null) {
139 14
            $unregistered->unregister();
140
        }
141
142 14
        if ($this->debug) {
143 14
            $registered->debug();
144
        }
145
146 14
        $registered->register();
147 14
    }
148
149 14
    private function runBootstrap(Container $container, array $bootstrapList): void
150
    {
151 14
        (new BootstrapRunner($container, $bootstrapList))->run();
152 14
    }
153
}
154