Passed
Push — master ( de73a2...a30a29 )
by Sergei
02:08
created

ApplicationRunner   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 1 Features 0
Metric Value
eloc 49
c 3
b 1
f 0
dl 0
loc 181
ccs 54
cts 54
cp 1
rs 10
wmc 21

13 Methods

Rating   Name   Duplication   Size   Complexity  
A withBootstrap() 0 5 1
A withoutBootstrap() 0 5 1
A withCheckingEvents() 0 5 1
A __construct() 0 5 1
A runBootstrap() 0 4 2
A getContainer() 0 9 2
A checkEvents() 0 5 3
A withConfig() 0 5 1
A withoutCheckingEvents() 0 5 1
A withContainer() 0 5 1
A getConfig() 0 3 1
A createDefaultConfig() 0 3 1
A createDefaultContainer() 0 21 5
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\Definitions\Exception\InvalidConfigException;
16
use Yiisoft\Di\Container;
17
use Yiisoft\Di\ContainerConfig;
18
use Yiisoft\Yii\Event\ListenerConfigurationChecker;
19
20
/**
21
 * Provides basic functionality for creating adapters.
22
 */
23
abstract class ApplicationRunner implements RunnerInterface
24
{
25
    protected bool $debug;
26
    protected string $rootPath;
27
    protected ?string $environment;
28
    protected ?ConfigInterface $config = null;
29
    protected ?ContainerInterface $container = null;
30
    protected ?string $bootstrapGroup = null;
31
    protected ?string $eventsGroup = null;
32
33
    /**
34
     * @param string $rootPath The absolute path to the project root.
35
     * @param bool $debug Whether the debug mode is enabled.
36
     * @param string|null $environment The environment name.
37
     */
38 14
    public function __construct(string $rootPath, bool $debug, ?string $environment)
39
    {
40 14
        $this->rootPath = $rootPath;
41 14
        $this->debug = $debug;
42 14
        $this->environment = $environment;
43
    }
44
45
    abstract public function run(): void;
46
47
    /**
48
     * Returns a new instance with the specified bootstrap configuration group name.
49
     *
50
     * @param string $bootstrapGroup The bootstrap configuration group name.
51
     *
52
     * @return static
53
     */
54 3
    public function withBootstrap(string $bootstrapGroup): static
55
    {
56 3
        $new = clone $this;
57 3
        $new->bootstrapGroup = $bootstrapGroup;
58 3
        return $new;
59
    }
60
61
    /**
62
     * Returns a new instance with bootstrapping disabled.
63
     *
64
     * @return static
65
     */
66 2
    public function withoutBootstrap(): static
67
    {
68 2
        $new = clone $this;
69 2
        $new->bootstrapGroup = null;
70 2
        return $new;
71
    }
72
73
    /**
74
     * Returns a new instance with the specified name of event configuration group to check.
75
     *
76
     * Note: The configuration of events is checked in debug mode only.
77
     *
78
     * @param string $eventsGroup Name of event configuration group to check.
79
     *
80
     * @return static
81
     */
82 3
    public function withCheckingEvents(string $eventsGroup): static
83
    {
84 3
        $new = clone $this;
85 3
        $new->eventsGroup = $eventsGroup;
86 3
        return $new;
87
    }
88
89
    /**
90
     * Returns a new instance with disabled event configuration check.
91
     *
92
     * @return static
93
     */
94 2
    public function withoutCheckingEvents(): static
95
    {
96 2
        $new = clone $this;
97 2
        $new->eventsGroup = null;
98 2
        return $new;
99
    }
100
101
    /**
102
     * Returns a new instance with the specified config instance {@see ConfigInterface}.
103
     *
104
     * @param ConfigInterface $config The config instance.
105
     *
106
     * @return static
107
     */
108 3
    public function withConfig(ConfigInterface $config): static
109
    {
110 3
        $new = clone $this;
111 3
        $new->config = $config;
112 3
        return $new;
113
    }
114
115
    /**
116
     * Returns a new instance with the specified container instance {@see ContainerInterface}.
117
     *
118
     * @param ContainerInterface $container The container instance.
119
     *
120
     * @return static
121
     */
122 4
    public function withContainer(ContainerInterface $container): static
123
    {
124 4
        $new = clone $this;
125 4
        $new->container = $container;
126 4
        return $new;
127
    }
128
129
    /**
130
     * @throws ErrorException|RuntimeException
131
     */
132 4
    protected function runBootstrap(ConfigInterface $config, ContainerInterface $container): void
133
    {
134 4
        if ($this->bootstrapGroup !== null) {
135 2
            (new BootstrapRunner($container, $config->get($this->bootstrapGroup)))->run();
136
        }
137
    }
138
139
    /**
140
     * @throws ContainerExceptionInterface|ErrorException|NotFoundExceptionInterface
141
     */
142 4
    protected function checkEvents(ConfigInterface $config, ContainerInterface $container): void
143
    {
144 4
        if ($this->debug && $this->eventsGroup !== null) {
145
            /** @psalm-suppress MixedMethodCall */
146 2
            $container->get(ListenerConfigurationChecker::class)->check($config->get($this->eventsGroup));
147
        }
148
    }
149
150
    /**
151
     * @throws ErrorException
152
     */
153 9
    protected function getConfig(): ConfigInterface
154
    {
155 9
        return $this->config ??= $this->createDefaultConfig();
156
    }
157
158
    /**
159
     * @throws ErrorException|InvalidConfigException
160
     */
161 7
    protected function getContainer(ConfigInterface $config, string $definitionEnvironment): ContainerInterface
162
    {
163 7
        $this->container ??= $this->createDefaultContainer($config, $definitionEnvironment);
164
165 7
        if ($this->container instanceof Container) {
166 6
            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

166
            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...
167
        }
168
169 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...
170
    }
171
172
    /**
173
     * @throws ErrorException
174
     */
175 8
    protected function createDefaultConfig(): Config
176
    {
177 8
        return ConfigFactory::create(new ConfigPaths($this->rootPath, 'config'), $this->environment);
178
    }
179
180
    /**
181
     * @throws ErrorException|InvalidConfigException
182
     */
183 6
    protected function createDefaultContainer(ConfigInterface $config, string $definitionEnvironment): Container
184
    {
185 6
        $containerConfig = ContainerConfig::create()->withValidate($this->debug);
186
187 6
        if ($config->has($definitionEnvironment)) {
188 6
            $containerConfig = $containerConfig->withDefinitions($config->get($definitionEnvironment));
189
        }
190
191 6
        if ($config->has("providers-$definitionEnvironment")) {
192 6
            $containerConfig = $containerConfig->withProviders($config->get("providers-$definitionEnvironment"));
193
        }
194
195 6
        if ($config->has("delegates-$definitionEnvironment")) {
196 6
            $containerConfig = $containerConfig->withDelegates($config->get("delegates-$definitionEnvironment"));
197
        }
198
199 6
        if ($config->has("tags-$definitionEnvironment")) {
200 6
            $containerConfig = $containerConfig->withTags($config->get("tags-$definitionEnvironment"));
201
        }
202
203 6
        return new Container($containerConfig);
204
    }
205
}
206