Passed
Pull Request — master (#39)
by Alexander
05:25 queued 02:31
created

ApplicationRunner::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 13
dl 0
loc 15
ccs 1
cts 1
cp 1
crap 1
rs 10

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;
6
7
use ErrorException;
8
use Psr\Container\ContainerExceptionInterface;
9
use Psr\Container\ContainerInterface;
10
use Psr\Container\NotFoundExceptionInterface;
11
use RuntimeException;
12
use Yiisoft\Config\Config;
13
use Yiisoft\Config\ConfigInterface;
14
use Yiisoft\Config\ConfigPaths;
15
use Yiisoft\Config\Modifier\RecursiveMerge;
16
use Yiisoft\Config\Modifier\ReverseMerge;
17
use Yiisoft\Definitions\Exception\InvalidConfigException;
18
use Yiisoft\Di\Container;
19
use Yiisoft\Di\ContainerConfig;
20
use Yiisoft\Yii\Event\ListenerConfigurationChecker;
21
22
/**
23
 * Provides basic functionality for creating adapters.
24
 */
25
abstract class ApplicationRunner implements RunnerInterface
26
{
27
    private ?ConfigInterface $config = null;
28
    private ?ContainerInterface $container = null;
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 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 config parameters group name.
42
     * @param array $nestedParamsGroups Configuration group names that included to config parameters group. This is
43
     * needed for recursive merge parameters.
44
     * @param array $nestedEventsGroups Configuration group names that included to events' configuration group. This is
45
     * needed for reverse and recursive merge events' configurations.
46
     *
47
     * @psalm-param list<string> $nestedParamsGroups
48
     * @psalm-param list<string> $nestedEventsGroups
49
     */
50 13
    public function __construct(
51
        protected string $rootPath,
52
        protected bool $debug,
53
        protected bool $checkEvents,
54
        protected ?string $environment,
55
        protected string $bootstrapGroup,
56
        protected string $eventsGroup,
57
        protected string $diGroup,
58
        protected string $diProvidersGroup,
59
        protected string $diDelegatesGroup,
60
        protected string $diTagsGroup,
61
        protected string $paramsGroup,
62
        protected array $nestedParamsGroups,
63
        protected array $nestedEventsGroups,
64
    ) {
65 13
    }
66
67
    abstract public function run(): void;
68
69
    /**
70
     * Returns a new instance with the specified config instance {@see ConfigInterface}.
71
     *
72
     * @param ConfigInterface $config The config instance.
73
     */
74 4
    final public function withConfig(ConfigInterface $config): static
75
    {
76 4
        $new = clone $this;
77 4
        $new->config = $config;
78 4
        return $new;
79
    }
80
81
    /**
82
     * Returns a new instance with the specified container instance {@see ContainerInterface}.
83
     *
84
     * @param ContainerInterface $container The container instance.
85
     */
86 4
    final public function withContainer(ContainerInterface $container): static
87
    {
88 4
        $new = clone $this;
89 4
        $new->container = $container;
90 4
        return $new;
91
    }
92
93
    /**
94
     * @throws ErrorException|RuntimeException
95
     */
96 3
    final protected function runBootstrap(): void
97
    {
98 3
        $bootstrapList = $this->getConfiguration($this->bootstrapGroup);
99 3
        if (empty($bootstrapList)) {
100
            return;
101
        }
102
103 3
        (new BootstrapRunner($this->getContainer(), $bootstrapList))->run();
104
    }
105
106
    /**
107
     * @throws ContainerExceptionInterface|ErrorException|NotFoundExceptionInterface
108
     */
109 3
    final protected function checkEvents(): void
110
    {
111
        if (
112 3
            $this->debug
113 3
            && $this->checkEvents
114 3
            && null !== $configuration = $this->getConfiguration($this->eventsGroup)
115
        ) {
116
            /** @psalm-suppress MixedMethodCall */
117 3
            $this->getContainer()
118 3
                ->get(ListenerConfigurationChecker::class)
119 3
                ->check($configuration);
120
        }
121
    }
122
123
    /**
124
     * @throws ErrorException
125
     */
126 10
    final protected function getConfig(): ConfigInterface
127
    {
128 10
        return $this->config ??= $this->createDefaultConfig();
129
    }
130
131
    /**
132
     * @throws ErrorException|InvalidConfigException
133
     */
134 9
    final protected function getContainer(): ContainerInterface
135
    {
136 9
        $this->container ??= $this->createDefaultContainer();
137
138 9
        if ($this->container instanceof Container) {
139 8
            return $this->container->get(ContainerInterface::class);
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

139
            return $this->container->/** @scrutinizer ignore-call */ get(ContainerInterface::class);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
140
        }
141
142 1
        return $this->container;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->container could return the type null which is incompatible with the type-hinted return Psr\Container\ContainerInterface. Consider adding an additional type-check to rule them out.
Loading history...
143
    }
144
145 7
    final protected function getConfiguration(string $name): ?array
146
    {
147 7
        $config = $this->getConfig();
148 7
        return $config->has($name) ? $config->get($name) : null;
149
    }
150
151
    /**
152
     * @throws ErrorException
153
     */
154 7
    private function createDefaultConfig(): Config
155
    {
156 7
        $paramsGroups = [$this->paramsGroup, ...$this->nestedParamsGroups];
157 7
        $eventsGroups = [$this->eventsGroup, ...$this->nestedEventsGroups];
158
159 7
        return new Config(
160 7
            new ConfigPaths($this->rootPath, 'config'),
161 7
            $this->environment,
162 7
            [
163 7
                ReverseMerge::groups(...$eventsGroups),
0 ignored issues
show
Bug introduced by
It seems like $eventsGroups can also be of type array; however, parameter $groups of Yiisoft\Config\Modifier\ReverseMerge::groups() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

163
                ReverseMerge::groups(/** @scrutinizer ignore-type */ ...$eventsGroups),
Loading history...
164 7
                RecursiveMerge::groups(...$paramsGroups, ...$eventsGroups),
0 ignored issues
show
Bug introduced by
It seems like $paramsGroups can also be of type array; however, parameter $groups of Yiisoft\Config\Modifier\RecursiveMerge::groups() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

164
                RecursiveMerge::groups(/** @scrutinizer ignore-type */ ...$paramsGroups, ...$eventsGroups),
Loading history...
165 7
            ],
166 7
            $this->paramsGroup,
167 7
        );
168
    }
169
170
    /**
171
     * @throws ErrorException|InvalidConfigException
172
     */
173 6
    private function createDefaultContainer(): Container
174
    {
175 6
        $containerConfig = ContainerConfig::create()->withValidate($this->debug);
176
177 6
        $config = $this->getConfig();
178
179 6
        if (null !== $definitions = $this->getConfiguration($this->diGroup)) {
180 6
            $containerConfig = $containerConfig->withDefinitions($definitions);
181
        }
182
183 6
        if (null !== $providers = $this->getConfiguration($this->diProvidersGroup)) {
184 6
            $containerConfig = $containerConfig->withProviders($providers);
185
        }
186
187 6
        if (null !== $delegates = $this->getConfiguration($this->diDelegatesGroup)) {
188 6
            $containerConfig = $containerConfig->withDelegates($delegates);
189
        }
190
191 6
        if (null !== $tags = $this->getConfiguration($this->diTagsGroup)) {
192 6
            $containerConfig = $containerConfig->withTags($tags);
193
        }
194
195 6
        $containerConfig = $containerConfig->withDefinitions(
196 6
            array_merge($containerConfig->getDefinitions(), [ConfigInterface::class => $config])
197 6
        );
198
199 6
        return new Container($containerConfig);
200
    }
201
}
202