Passed
Push — master ( 84636c...cbf469 )
by Alexander
01:58
created

ApplicationRunner   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 179
Duplicated Lines 0 %

Test Coverage

Coverage 98.18%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 47
dl 0
loc 179
ccs 54
cts 55
cp 0.9818
rs 10
c 1
b 0
f 0
wmc 20

13 Methods

Rating   Name   Duplication   Size   Complexity  
A withBootstrap() 0 5 1
A withoutBootstrap() 0 5 1
A withConfig() 0 5 1
A withoutCheckingEvents() 0 5 1
A withContainer() 0 5 1
A withCheckingEvents() 0 5 1
A __construct() 0 5 1
A runBootstrap() 0 4 2
A checkEvents() 0 5 3
A getContainer() 0 9 2
A createDefaultContainer() 0 17 4
A getConfig() 0 3 1
A createDefaultConfig() 0 3 1
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 12
    public function __construct(string $rootPath, bool $debug, ?string $environment)
39
    {
40 12
        $this->rootPath = $rootPath;
41 12
        $this->debug = $debug;
42 12
        $this->environment = $environment;
43 12
    }
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 and disables the use of bootstrap configuration group.
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 configuration group of events name for check.
75
     *
76
     * Note: The configuration of events is checked only in debug mode.
77
     *
78
     * @param string $eventsGroup The configuration group name of events for 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 and disables checking of the event configuration group.
91
     *
92
     * Note: The configuration of events is checked only in debug mode.
93
     *
94
     * @return static
95
     */
96 2
    public function withoutCheckingEvents(): static
97
    {
98 2
        $new = clone $this;
99 2
        $new->eventsGroup = null;
100 2
        return $new;
101
    }
102
103
    /**
104
     * Returns a new instance with the specified config instance {@see ConfigInterface}.
105
     *
106
     * @param ConfigInterface $config The config instance.
107
     *
108
     * @return static
109
     */
110 3
    public function withConfig(ConfigInterface $config): static
111
    {
112 3
        $new = clone $this;
113 3
        $new->config = $config;
114 3
        return $new;
115
    }
116
117
    /**
118
     * Returns a new instance with the specified container instance {@see ContainerInterface}.
119
     *
120
     * @param ContainerInterface $container The container instance.
121
     *
122
     * @return static
123
     */
124 3
    public function withContainer(ContainerInterface $container): static
125
    {
126 3
        $new = clone $this;
127 3
        $new->container = $container;
128 3
        return $new;
129
    }
130
131
    /**
132
     * @throws ErrorException|RuntimeException
133
     */
134 4
    protected function runBootstrap(ConfigInterface $config, ContainerInterface $container): void
135
    {
136 4
        if ($this->bootstrapGroup !== null) {
137 2
            (new BootstrapRunner($container, $config->get($this->bootstrapGroup)))->run();
138
        }
139 4
    }
140
141
    /**
142
     * @throws ContainerExceptionInterface|ErrorException|NotFoundExceptionInterface
143
     */
144 4
    protected function checkEvents(ConfigInterface $config, ContainerInterface $container): void
145
    {
146 4
        if ($this->debug && $this->eventsGroup !== null) {
147
            /** @psalm-suppress MixedMethodCall */
148 2
            $container->get(ListenerConfigurationChecker::class)->check($config->get($this->eventsGroup));
149
        }
150 3
    }
151
152
    /**
153
     * @throws ErrorException
154
     */
155 8
    protected function getConfig(): ConfigInterface
156
    {
157 8
        return $this->config ??= $this->createDefaultConfig();
158
    }
159
160
    /**
161
     * @throws ErrorException|InvalidConfigException
162
     */
163 6
    protected function getContainer(ConfigInterface $config, string $definitionEnvironment): ContainerInterface
164
    {
165 6
        $this->container ??= $this->createDefaultContainer($config, $definitionEnvironment);
166
167 6
        if ($this->container instanceof Container) {
168 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

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