Passed
Pull Request — master (#39)
by Alexander
12:58 queued 10:30
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 string|null $environment The environment name.
34
     *
35
     * @psalm-param list<string> $nestedParamsGroups
36
     * @psalm-param list<string> $nestedEventsGroups
37
     */
38 11
    public function __construct(
39
        protected string $rootPath,
40
        protected bool $debug,
41
        protected bool $checkEvents,
42
        protected ?string $environment,
43
        protected string $bootstrapGroup,
44
        protected string $eventsGroup,
45
        protected string $diGroup,
46
        protected string $diProvidersGroup,
47
        protected string $diDelegatesGroup,
48
        protected string $diTagsGroup,
49
        protected string $paramsGroup,
50
        protected array $nestedParamsGroups,
51
        protected array $nestedEventsGroups,
52
    ) {
53 11
    }
54
55
    abstract public function run(): void;
56
57
    /**
58
     * Returns a new instance with the specified config instance {@see ConfigInterface}.
59
     *
60
     * @param ConfigInterface $config The config instance.
61
     */
62 3
    final public function withConfig(ConfigInterface $config): static
63
    {
64 3
        $new = clone $this;
65 3
        $new->config = $config;
66 3
        return $new;
67
    }
68
69
    /**
70
     * Returns a new instance with the specified container instance {@see ContainerInterface}.
71
     *
72
     * @param ContainerInterface $container The container instance.
73
     */
74 4
    final public function withContainer(ContainerInterface $container): static
75
    {
76 4
        $new = clone $this;
77 4
        $new->container = $container;
78 4
        return $new;
79
    }
80
81
    /**
82
     * @throws ErrorException|RuntimeException
83
     */
84 3
    final protected function runBootstrap(): void
85
    {
86 3
        $bootstrapList = $this->getConfiguration($this->bootstrapGroup);
87 3
        if (empty($bootstrapList)) {
88
            return;
89
        }
90
91 3
        (new BootstrapRunner($this->getContainer(), $bootstrapList))->run();
92
    }
93
94
    /**
95
     * @throws ContainerExceptionInterface|ErrorException|NotFoundExceptionInterface
96
     */
97 3
    final protected function checkEvents(): void
98
    {
99
        if (
100 3
            $this->debug
101 3
            && $this->checkEvents
102 3
            && null !== $configuration = $this->getConfiguration($this->eventsGroup)
103
        ) {
104
            /** @psalm-suppress MixedMethodCall */
105 3
            $this->getContainer()
106 3
                ->get(ListenerConfigurationChecker::class)
107 3
                ->check($configuration);
108
        }
109
    }
110
111
    /**
112
     * @throws ErrorException
113
     */
114 8
    final protected function getConfig(): ConfigInterface
115
    {
116 8
        return $this->config ??= $this->createDefaultConfig();
117
    }
118
119
    /**
120
     * @throws ErrorException|InvalidConfigException
121
     */
122 8
    final protected function getContainer(): ContainerInterface
123
    {
124 8
        $this->container ??= $this->createDefaultContainer();
125
126 8
        if ($this->container instanceof Container) {
127 7
            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

127
            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...
128
        }
129
130 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...
131
    }
132
133 6
    final protected function getConfiguration(string $name): ?array
134
    {
135 6
        $config = $this->getConfig();
136 6
        return $config->has($name) ? $config->get($name) : null;
137
    }
138
139
    /**
140
     * @throws ErrorException
141
     */
142 6
    private function createDefaultConfig(): Config
143
    {
144 6
        $paramsGroups = [$this->paramsGroup, ...$this->nestedParamsGroups];
145 6
        $eventsGroups = [$this->eventsGroup, ...$this->nestedEventsGroups];
146
147 6
        return new Config(
148 6
            new ConfigPaths($this->rootPath, 'config'),
149 6
            $this->environment,
150 6
            [
151 6
                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

151
                ReverseMerge::groups(/** @scrutinizer ignore-type */ ...$eventsGroups),
Loading history...
152 6
                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

152
                RecursiveMerge::groups(/** @scrutinizer ignore-type */ ...$paramsGroups, ...$eventsGroups),
Loading history...
153 6
            ],
154 6
            $this->paramsGroup,
155 6
        );
156
    }
157
158
    /**
159
     * @throws ErrorException|InvalidConfigException
160
     */
161 5
    private function createDefaultContainer(): Container
162
    {
163 5
        $containerConfig = ContainerConfig::create()->withValidate($this->debug);
164
165 5
        $config = $this->getConfig();
166
167 5
        if (null !== $definitions = $this->getConfiguration($this->diGroup)) {
168 5
            $containerConfig = $containerConfig->withDefinitions($definitions);
169
        }
170
171 5
        if (null !== $providers = $this->getConfiguration($this->diProvidersGroup)) {
172 5
            $containerConfig = $containerConfig->withProviders($providers);
173
        }
174
175 5
        if (null !== $delegates = $this->getConfiguration($this->diDelegatesGroup)) {
176 5
            $containerConfig = $containerConfig->withDelegates($delegates);
177
        }
178
179 5
        if (null !== $tags = $this->getConfiguration($this->diTagsGroup)) {
180 5
            $containerConfig = $containerConfig->withTags($tags);
181
        }
182
183 5
        $containerConfig = $containerConfig->withDefinitions(
184 5
            array_merge($containerConfig->getDefinitions(), [ConfigInterface::class => $config])
185 5
        );
186
187 5
        return new Container($containerConfig);
188
    }
189
}
190