Passed
Push — master ( 0e91c9...6f8172 )
by Alexander
02:51
created

RoadRunnerHttpApplicationRunner::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 14
nc 1
nop 13
dl 0
loc 29
ccs 15
cts 15
cp 1
crap 1
rs 9.7998
c 0
b 0
f 0

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\RoadRunner;
6
7
use ErrorException;
8
use JsonException;
9
use Psr\Container\ContainerExceptionInterface;
10
use Psr\Container\ContainerInterface;
11
use Psr\Container\NotFoundExceptionInterface;
12
use Psr\Http\Message\ResponseInterface;
13
use Spiral\RoadRunner\Http\PSR7WorkerInterface;
14
use Throwable;
15
use Yiisoft\Definitions\Exception\CircularReferenceException;
16
use Yiisoft\Definitions\Exception\InvalidConfigException;
17
use Yiisoft\Definitions\Exception\NotInstantiableException;
18
use Yiisoft\Di\NotFoundException;
19
use Yiisoft\Di\StateResetter;
20
use Yiisoft\ErrorHandler\ErrorHandler;
21
use Yiisoft\ErrorHandler\Renderer\HtmlRenderer;
22
use Yiisoft\Log\Logger;
23
use Yiisoft\Log\Target\File\FileTarget;
24
use Yiisoft\Yii\Http\Application;
25
use Yiisoft\Yii\Runner\ApplicationRunner;
26
27
use function gc_collect_cycles;
28
29
/**
30
 * `RoadRunnerHttpApplicationRunner` runs the Yii HTTP application using RoadRunner.
31
 */
32
final class RoadRunnerHttpApplicationRunner extends ApplicationRunner
33
{
34
    private ?ErrorHandler $temporaryErrorHandler = null;
35
    private ?PSR7WorkerInterface $psr7Worker = 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
     *
54
     * @psalm-param list<string> $nestedParamsGroups
55
     * @psalm-param list<string> $nestedEventsGroups
56
     */
57 9
    public function __construct(
58
        string $rootPath,
59
        bool $debug = false,
60
        bool $checkEvents = false,
61
        ?string $environment = null,
62
        string $bootstrapGroup = 'bootstrap-web',
63
        string $eventsGroup = 'events-web',
64
        string $diGroup = 'di-web',
65
        string $diProvidersGroup = 'di-providers-web',
66
        string $diDelegatesGroup = 'di-delegates-web',
67
        string $diTagsGroup = 'di-tags-web',
68
        string $paramsGroup = 'params-web',
69
        array $nestedParamsGroups = ['params'],
70
        array $nestedEventsGroups = ['events'],
71
    ) {
72 9
        parent::__construct(
73 9
            $rootPath,
74 9
            $debug,
75 9
            $checkEvents,
76 9
            $environment,
77 9
            $bootstrapGroup,
78 9
            $eventsGroup,
79 9
            $diGroup,
80 9
            $diProvidersGroup,
81 9
            $diDelegatesGroup,
82 9
            $diTagsGroup,
83 9
            $paramsGroup,
84 9
            $nestedParamsGroups,
85 9
            $nestedEventsGroups,
86 9
        );
87
    }
88
89
    /**
90
     * Returns a new instance with the specified temporary error handler instance {@see ErrorHandler}.
91
     *
92
     * A temporary error handler is needed to handle the creation of configuration and container instances,
93
     * then the error handler configured in your application configuration will be used.
94
     *
95
     * @param ErrorHandler $temporaryErrorHandler The temporary error handler instance.
96
     */
97 2
    public function withTemporaryErrorHandler(ErrorHandler $temporaryErrorHandler): self
98
    {
99 2
        $new = clone $this;
100 2
        $new->temporaryErrorHandler = $temporaryErrorHandler;
101 2
        return $new;
102
    }
103
104
    /**
105
     * Returns a new instance with the specified PSR-7 worker instance {@see PSR7WorkerInterface}.
106
     *
107
     * @param PSR7WorkerInterface $worker The PSR-7 worker instance.
108
     */
109 9
    public function withPsr7Worker(PSR7WorkerInterface $worker): self
110
    {
111 9
        $new = clone $this;
112 9
        $new->psr7Worker = $worker;
113 9
        return $new;
114
    }
115
116
    /**
117
     * {@inheritDoc}
118
     *
119
     * @throws CircularReferenceException|ErrorException|InvalidConfigException|JsonException
120
     * @throws ContainerExceptionInterface|NotFoundException|NotFoundExceptionInterface|NotInstantiableException
121
     */
122 8
    public function run(): void
123
    {
124
        // Register temporary error handler to catch error while container is building.
125 8
        $temporaryErrorHandler = $this->createTemporaryErrorHandler();
126 8
        $this->registerErrorHandler($temporaryErrorHandler);
127
128 8
        $container = $this->getContainer();
129
130
        // Register error handler with real container-configured dependencies.
131
        /** @var ErrorHandler $actualErrorHandler */
132 8
        $actualErrorHandler = $container->get(ErrorHandler::class);
133 8
        $this->registerErrorHandler($actualErrorHandler, $temporaryErrorHandler);
134
135 8
        $this->runBootstrap();
136 8
        $this->checkEvents();
137
138 7
        $worker = new RoadRunnerWorker($container, $this->psr7Worker);
139
140
        /** @var Application $application */
141 7
        $application = $container->get(Application::class);
142 7
        $application->start();
143
144 7
        while (true) {
145 7
            $request = $worker->waitRequest();
146 7
            $response = null;
147
148 7
            if ($request === null) {
149 7
                break;
150
            }
151
152 6
            if ($request instanceof Throwable) {
153 1
                $response = $worker->respondWithError($request);
154 1
                $this->afterRespond($application, $container, $response);
155 1
                continue;
156
            }
157
158
            try {
159 5
                $response = $application->handle($request);
160 4
                $worker->respond($response);
161 1
            } catch (Throwable $t) {
162 1
                $response = $worker->respondWithError($t, $request);
163
            } finally {
164 5
                $this->afterRespond($application, $container, $response);
165
            }
166
        }
167
168 7
        $application->shutdown();
169
    }
170
171 8
    private function createTemporaryErrorHandler(): ErrorHandler
172
    {
173 8
        if ($this->temporaryErrorHandler !== null) {
174 1
            return $this->temporaryErrorHandler;
175
        }
176
177 7
        $logger = new Logger([new FileTarget("$this->rootPath/runtime/logs/app.log")]);
178 7
        return new ErrorHandler($logger, new HtmlRenderer());
179
    }
180
181
    /**
182
     * @throws ErrorException
183
     */
184 8
    private function registerErrorHandler(ErrorHandler $registered, ErrorHandler $unregistered = null): void
185
    {
186 8
        $unregistered?->unregister();
187
188 8
        if ($this->debug) {
189 8
            $registered->debug();
190
        }
191
192 8
        $registered->register();
193
    }
194
195 6
    private function afterRespond(
196
        Application $application,
197
        ContainerInterface $container,
198
        ?ResponseInterface $response,
199
    ): void {
200 6
        $application->afterEmit($response);
201
        /** @psalm-suppress MixedMethodCall */
202 6
        $container
203 6
            ->get(StateResetter::class)
204 6
            ->reset(); // We should reset the state of such services every request.
205 6
        gc_collect_cycles();
206
    }
207
}
208