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