HttpApplicationRunner::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 31
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 15
c 1
b 0
f 1
nc 1
nop 14
dl 0
loc 31
ccs 16
cts 16
cp 1
crap 1
rs 9.7666

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Runner\Http;
6
7
use ErrorException;
8
use Psr\Container\ContainerExceptionInterface;
9
use Psr\Container\NotFoundExceptionInterface;
10
use Psr\Http\Message\ResponseInterface;
11
use Psr\Http\Message\ServerRequestInterface;
12
use Throwable;
13
use Yiisoft\Definitions\Exception\CircularReferenceException;
14
use Yiisoft\Definitions\Exception\InvalidConfigException;
15
use Yiisoft\Definitions\Exception\NotInstantiableException;
16
use Yiisoft\Di\NotFoundException;
17
use Yiisoft\ErrorHandler\ErrorHandler;
0 ignored issues
show
Bug introduced by
The type Yiisoft\ErrorHandler\ErrorHandler 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...
18
use Yiisoft\ErrorHandler\Middleware\ErrorCatcher;
19
use Yiisoft\ErrorHandler\Renderer\HtmlRenderer;
20
use Yiisoft\Http\Method;
21
use Yiisoft\Log\Logger;
22
use Yiisoft\Log\Target\File\FileTarget;
23
use Yiisoft\Yii\Http\Application;
24
use Yiisoft\Yii\Http\Handler\ThrowableHandler;
25
use Yiisoft\Yii\Runner\ApplicationRunner;
26
use Yiisoft\Yii\Runner\Http\Exception\HeadersHaveBeenSentException;
27
28
use function microtime;
29
30
/**
31
 * `HttpApplicationRunner` runs the Yii HTTP application.
32
 */
33
final class HttpApplicationRunner extends ApplicationRunner
34
{
35
    private ?ErrorHandler $temporaryErrorHandler = null;
36
37
    /**
38
     * @param string $rootPath The absolute path to the project root.
39
     * @param bool $debug Whether the debug mode is enabled.
40
     * @param bool $checkEvents Whether to check events' configuration.
41
     * @param string|null $environment The environment name.
42
     * @param string $bootstrapGroup The bootstrap configuration group name.
43
     * @param string $eventsGroup The events' configuration group name.
44
     * @param string $diGroup The container definitions' configuration group name.
45
     * @param string $diProvidersGroup The container providers' configuration group name.
46
     * @param string $diDelegatesGroup The container delegates' configuration group name.
47
     * @param string $diTagsGroup The container tags' configuration group name.
48
     * @param string $paramsGroup The configuration parameters group name.
49
     * @param array $nestedParamsGroups Configuration group names that are included into configuration parameters group.
50
     * This is needed for recursive merging of parameters.
51
     * @param array $nestedEventsGroups Configuration group names that are included into events' configuration group.
52
     * This is needed for reverse and recursive merge of events' configurations.
53
     * @param object[] $configModifiers Modifiers for {@see Config}.
54
     *
55
     * @psalm-param list<string> $nestedParamsGroups
56
     * @psalm-param list<string> $nestedEventsGroups
57
     * @psalm-param list<object> $configModifiers
58
     */
59 5
    public function __construct(
60
        string $rootPath,
61
        bool $debug = false,
62
        bool $checkEvents = false,
63
        ?string $environment = null,
64
        string $bootstrapGroup = 'bootstrap-web',
65
        string $eventsGroup = 'events-web',
66
        string $diGroup = 'di-web',
67
        string $diProvidersGroup = 'di-providers-web',
68
        string $diDelegatesGroup = 'di-delegates-web',
69
        string $diTagsGroup = 'di-tags-web',
70
        string $paramsGroup = 'params-web',
71
        array $nestedParamsGroups = ['params'],
72
        array $nestedEventsGroups = ['events'],
73
        array $configModifiers = [],
74
    ) {
75 5
        parent::__construct(
76 5
            $rootPath,
77 5
            $debug,
78 5
            $checkEvents,
79 5
            $environment,
80 5
            $bootstrapGroup,
81 5
            $eventsGroup,
82 5
            $diGroup,
83 5
            $diProvidersGroup,
84 5
            $diDelegatesGroup,
85 5
            $diTagsGroup,
86 5
            $paramsGroup,
87 5
            $nestedParamsGroups,
88 5
            $nestedEventsGroups,
89 5
            $configModifiers,
90 5
        );
91
    }
92
93
    /**
94
     * Returns a new instance with the specified temporary error handler instance {@see ErrorHandler}.
95
     *
96
     * A temporary error handler is needed to handle the creation of configuration and container instances,
97
     * then the error handler configured in your application configuration will be used.
98
     *
99
     * @param ErrorHandler $temporaryErrorHandler The temporary error handler instance.
100
     */
101 2
    public function withTemporaryErrorHandler(ErrorHandler $temporaryErrorHandler): self
102
    {
103 2
        $new = clone $this;
104 2
        $new->temporaryErrorHandler = $temporaryErrorHandler;
105 2
        return $new;
106
    }
107
108
    /**
109
     * {@inheritDoc}
110
     *
111
     * @throws CircularReferenceException|ErrorException|HeadersHaveBeenSentException|InvalidConfigException
112
     * @throws ContainerExceptionInterface|NotFoundException|NotFoundExceptionInterface|NotInstantiableException
113
     */
114 4
    public function run(): void
115
    {
116 4
        $startTime = microtime(true);
117
118
        // Register temporary error handler to catch error while container is building.
119 4
        $temporaryErrorHandler = $this->createTemporaryErrorHandler();
120 4
        $this->registerErrorHandler($temporaryErrorHandler);
121
122 4
        $container = $this->getContainer();
123
124
        // Register error handler with real container-configured dependencies.
125
        /** @var ErrorHandler $actualErrorHandler */
126 4
        $actualErrorHandler = $container->get(ErrorHandler::class);
127 4
        $this->registerErrorHandler($actualErrorHandler, $temporaryErrorHandler);
128
129 4
        $this->runBootstrap();
130 4
        $this->checkEvents();
131
132
        /** @var Application $application */
133 4
        $application = $container->get(Application::class);
134
135
        /**
136
         * @var RequestFactory $requestFactory
137
         */
138 4
        $requestFactory = $container->get(RequestFactory::class);
139 4
        $request = $requestFactory->create();
140
141 4
        $request = $request->withAttribute('applicationStartTime', $startTime);
142
        try {
143 4
            $application->start();
144 4
            $response = $application->handle($request);
145 3
            $this->emit($request, $response);
146 1
        } catch (Throwable $throwable) {
147 1
            $handler = new ThrowableHandler($throwable);
148
            /**
149
             * @var ResponseInterface
150
             * @psalm-suppress MixedMethodCall
151
             */
152 1
            $response = $container
153 1
                ->get(ErrorCatcher::class)
154 1
                ->process($request, $handler);
155 1
            $this->emit($request, $response);
156
        } finally {
157 4
            $application->afterEmit($response ?? null);
158 4
            $application->shutdown();
159
        }
160
    }
161
162 4
    private function createTemporaryErrorHandler(): ErrorHandler
163
    {
164 4
        if ($this->temporaryErrorHandler !== null) {
165 1
            return $this->temporaryErrorHandler;
166
        }
167
168 3
        $logger = new Logger([new FileTarget("$this->rootPath/runtime/logs/app.log")]);
169 3
        return new ErrorHandler($logger, new HtmlRenderer());
170
    }
171
172
    /**
173
     * @throws HeadersHaveBeenSentException
174
     */
175 4
    private function emit(ServerRequestInterface $request, ResponseInterface $response): void
176
    {
177 4
        (new SapiEmitter())->emit($response, $request->getMethod() === Method::HEAD);
0 ignored issues
show
Bug introduced by
The type Yiisoft\Yii\Runner\Http\SapiEmitter 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...
178
    }
179
180
    /**
181
     * @throws ErrorException
182
     */
183 4
    private function registerErrorHandler(ErrorHandler $registered, ErrorHandler $unregistered = null): void
184
    {
185 4
        $unregistered?->unregister();
186
187 4
        if ($this->debug) {
188 4
            $registered->debug();
189
        }
190
191 4
        $registered->register();
192
    }
193
}
194