Passed
Push — master ( 219199...627bc7 )
by Sergei
04:09 queued 01:41
created

TestApplicationRunner::withRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 12
c 2
b 0
f 0
nc 1
nop 8
dl 0
loc 23
ccs 0
cts 19
cp 0
crap 2
rs 9.8666

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\Testing;
6
7
use Psr\Container\ContainerInterface;
8
use Psr\Http\Message\ResponseInterface;
9
use Psr\Http\Message\ServerRequestInterface;
10
use Throwable;
11
use Yiisoft\Config\ConfigInterface;
12
use Yiisoft\Di\Container;
13
use Yiisoft\Di\ContainerConfig;
14
use Yiisoft\Di\ServiceProviderInterface;
15
use Yiisoft\ErrorHandler\Middleware\ErrorCatcher;
16
use Yiisoft\Yii\Http\Application;
17
use Yiisoft\Yii\Http\Handler\ThrowableHandler;
18
use Yiisoft\Yii\Runner\ApplicationRunner;
19
use Yiisoft\Yii\Runner\Http\ServerRequestFactory;
20
21
final class TestApplicationRunner extends ApplicationRunner
22
{
23
    private array $requestParameters = [];
24
    public ?ContainerInterface $container = null;
25
    /**
26
     * @var ServiceProviderInterface[]
27
     */
28
    private array $providers = [];
29
30
    /**
31
     * @param string $rootPath The absolute path to the project root.
32
     * @param bool $debug Whether the debug mode is enabled.
33
     * @param bool $checkEvents Whether to check events' configuration.
34
     * @param string|null $environment The environment name.
35
     * @param string $bootstrapGroup The bootstrap configuration group name.
36
     * @param string $eventsGroup The events' configuration group name.
37
     * @param string $diGroup The container definitions' configuration group name.
38
     * @param string $diProvidersGroup The container providers' configuration group name.
39
     * @param string $diDelegatesGroup The container delegates' configuration group name.
40
     * @param string $diTagsGroup The container tags' configuration group name.
41
     * @param string $paramsGroup The configuration parameters group name.
42
     * @param array $nestedParamsGroups Configuration group names that included into configuration parameters group.
43
     * This is needed for recursive merging of parameters.
44
     * @param array $nestedEventsGroups Configuration group names that included into events' configuration group. This
45
     * is needed for reverse and recursive merge of events' configurations.
46
     *
47
     * @psalm-param list<string> $nestedParamsGroups
48
     * @psalm-param list<string> $nestedEventsGroups
49
     */
50
    public function __construct(
51
        public ResponseGrabber $responseGrabber,
52
        string $rootPath,
53
        bool $debug = false,
54
        bool $checkEvents = false,
55
        ?string $environment = null,
56
        string $bootstrapGroup = 'bootstrap-web',
57
        string $eventsGroup = 'events-web',
58
        string $diGroup = 'di-web',
59
        string $diProvidersGroup = 'di-providers-web',
60
        string $diDelegatesGroup = 'di-delegates-web',
61
        string $diTagsGroup = 'di-tags-web',
62
        string $paramsGroup = 'params-web',
63
        array $nestedParamsGroups = ['params'],
64
        array $nestedEventsGroups = ['events'],
65
    ) {
66
        parent::__construct(
67
            $rootPath,
68
            $debug,
69
            $checkEvents,
70
            $environment,
71
            $bootstrapGroup,
72
            $eventsGroup,
73
            $diGroup,
74
            $diProvidersGroup,
75
            $diDelegatesGroup,
76
            $diTagsGroup,
77
            $paramsGroup,
78
            $nestedParamsGroups,
79
            $nestedEventsGroups,
80
        );
81
    }
82
83
    /**
84
     * {@inheritDoc}
85
     */
86
    public function run(): void
87
    {
88
        $this->preloadContainer();
89
90
        /** @var ContainerInterface $container */
91
        $container = $this->container;
92
93
        /** @var Application $application */
94
        $application = $container->get(Application::class);
95
96
        /**
97
         * @var ServerRequestInterface
98
         * @psalm-suppress MixedMethodCall
99
         */
100
        $serverRequest = $container
101
            ->get(ServerRequestFactory::class)
102
            ->createFromParameters(
103
                ...$this->requestParameters,
104
            );
105
106
        /**
107
         * @var ResponseInterface|null $response
108
         */
109
        $response = null;
110
        try {
111
            $application->start();
112
            $response = $application->handle($serverRequest);
113
        } catch (Throwable $throwable) {
114
            $handler = new ThrowableHandler($throwable);
115
            /**
116
             * @psalm-suppress MixedMethodCall
117
             */
118
            $response = $container
119
                ->get(ErrorCatcher::class)
120
                ->process($serverRequest, $handler);
121
        } finally {
122
            $application->afterEmit($response ?? null);
123
            $application->shutdown();
124
            $this->responseGrabber->setResponse($response);
125
        }
126
    }
127
128
    public function withRequest(
129
        string $method,
130
        string $url,
131
        array $queryParams = [],
132
        array $postParams = [],
133
        mixed $body = null,
134
        array $headers = [],
135
        array $cookies = [],
136
        array $files = [],
137
    ): void {
138
        $this->requestParameters = [
139
            'server' => [
140
                'SCRIPT_NAME' => '/index.php',
141
                'REQUEST_METHOD' => $method,
142
                'SERVER_PROTOCOL' => '1.1',
143
                'REQUEST_URI' => $url,
144
            ],
145
            'headers' => $headers,
146
            'cookies' => $cookies,
147
            'get' => $queryParams,
148
            'post' => $postParams,
149
            'files' => $files,
150
            'body' => $body,
151
        ];
152
    }
153
154
    public function preloadContainer(): void
155
    {
156
        /**
157
         * @psalm-suppress UnresolvableInclude
158
         */
159
        require_once $this->rootPath . '/autoload.php';
160
161
        $this->container = $this->createContainer();
162
163
        $this->runBootstrap();
164
        $this->checkEvents();
165
    }
166
167
    /**
168
     * @param ServiceProviderInterface[] $providers
169
     */
170
    public function addProviders(array $providers): void
171
    {
172
        $this->providers = array_merge($this->providers, $providers);
173
    }
174
175
    private function createContainer(): Container
176
    {
177
        $containerConfig = ContainerConfig::create()->withValidate($this->debug);
178
179
        $config = $this->getConfig();
180
181
        if (null !== $definitions = $this->getConfiguration($this->diGroup)) {
182
            $containerConfig = $containerConfig->withDefinitions($definitions);
183
        }
184
185
        if (null !== $providers = $this->getConfiguration($this->diProvidersGroup)) {
186
            $providers = array_merge($providers, $this->providers);
187
        } else {
188
            $providers = $this->providers;
189
        }
190
        $containerConfig = $containerConfig->withProviders($providers);
191
192
        if (null !== $delegates = $this->getConfiguration($this->diDelegatesGroup)) {
193
            $containerConfig = $containerConfig->withDelegates($delegates);
194
        }
195
196
        if (null !== $tags = $this->getConfiguration($this->diTagsGroup)) {
197
            $containerConfig = $containerConfig->withTags($tags);
198
        }
199
200
        $containerConfig = $containerConfig->withDefinitions(
201
            array_merge($containerConfig->getDefinitions(), [ConfigInterface::class => $config])
202
        );
203
204
        return new Container($containerConfig);
205
    }
206
}
207