Passed
Pull Request — master (#352)
by Rustam
04: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 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 35
c 1
b 0
f 0
nc 32
nop 0
dl 0
loc 66
ccs 29
cts 33
cp 0.8788
crap 3.016
rs 9.36

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