Passed
Push — bugfix/support-windows ( 0e99e7...b5ecf8 )
by Jesús
06:33 queued 02:55
created

GacelaConfig   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 362
Duplicated Lines 0 %

Test Coverage

Coverage 92.71%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
eloc 85
c 8
b 0
f 0
dl 0
loc 362
ccs 89
cts 96
cp 0.9271
rs 10
wmc 26

26 Methods

Rating   Name   Duplication   Size   Complexity  
A setFileCache() 0 6 1
A __construct() 0 6 1
A addAppConfigKeyValue() 0 5 1
A defaultPhpConfig() 0 4 1
A build() 0 18 1
A getExternalService() 0 3 1
A enableFileCache() 0 3 1
A addAppConfig() 0 5 1
A addSuffixTypeFacade() 0 5 1
A addExternalService() 0 5 1
A addMappingInterface() 0 3 1
A setProjectNamespaces() 0 5 1
A addSuffixTypeFactory() 0 5 1
A addPlugins() 0 5 1
A registerGenericListener() 0 6 1
A addAppConfigKeyValues() 0 5 1
A extendGacelaConfig() 0 5 1
A resetInMemoryCache() 0 5 1
A extendService() 0 6 1
A addSuffixTypeConfig() 0 5 1
A addSuffixTypeDependencyProvider() 0 5 1
A disableEventListeners() 0 5 1
A extendGacelaConfigs() 0 5 1
A addPlugin() 0 5 1
A registerSpecificListener() 0 6 1
A addBinding() 0 5 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Framework\Bootstrap;
6
7
use Closure;
8
use Gacela\Framework\Config\ConfigReaderInterface;
9
use Gacela\Framework\Config\GacelaConfigBuilder\AppConfigBuilder;
10
use Gacela\Framework\Config\GacelaConfigBuilder\BindingsBuilder;
11
use Gacela\Framework\Config\GacelaConfigBuilder\SuffixTypesBuilder;
12
use Gacela\Framework\Event\GacelaEventInterface;
13
14
final class GacelaConfig
15
{
16
    private AppConfigBuilder $appConfigBuilder;
17
18
    private SuffixTypesBuilder $suffixTypesBuilder;
19
20
    private BindingsBuilder $bindingsBuilder;
21
22
    /** @var array<string, class-string|object|callable> */
23
    private array $externalServices;
24
25
    private ?bool $shouldResetInMemoryCache = null;
26
27
    private ?bool $fileCacheEnabled = null;
28
29
    private ?string $fileCacheDirectory = null;
30
31
    /** @var list<string> */
32
    private ?array $projectNamespaces = null;
33
34
    /** @var array<string,mixed> */
35
    private ?array $configKeyValues = null;
36
37
    private ?bool $areEventListenersEnabled = null;
38
39
    /** @var list<callable> */
40
    private ?array $genericListeners = null;
41
42
    /** @var array<class-string,list<callable>> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string,list<callable>> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string,list<callable>>.
Loading history...
43
    private ?array $specificListeners = null;
44
45
    /** @var list<class-string> */
46
    private ?array $gacelaConfigsToExtend = null;
47
48
    /** @var list<class-string|callable> */
49
    private ?array $plugins = null;
50
51
    /** @var array<string,list<Closure>> */
52
    private array $servicesToExtend = [];
53
54
    /**
55
     * @param array<string,class-string|object|callable> $externalServices
56
     */
57 82
    public function __construct(array $externalServices = [])
58
    {
59 82
        $this->externalServices = $externalServices;
60 82
        $this->appConfigBuilder = new AppConfigBuilder();
61 82
        $this->suffixTypesBuilder = new SuffixTypesBuilder();
62 82
        $this->bindingsBuilder = new BindingsBuilder();
63
    }
64
65
    /**
66
     * Define 'config/*.php' as path, and 'config/local.php' as local path for the configuration.
67
     *
68
     * @return Closure(GacelaConfig):void
69
     */
70
    public static function defaultPhpConfig(): callable
71
    {
72
        return static function (self $config): void {
73
            $config->addAppConfig('config/*.php', 'config/local.php');
74
        };
75
    }
76
77
    /**
78
     * Define the path where the configuration will be stored.
79
     *
80
     * @param string $path define the path where Gacela will read all the config files
81
     * @param string $pathLocal define the path where Gacela will read the local config file
82
     * @param class-string<ConfigReaderInterface>|ConfigReaderInterface|null $reader Define the reader class which will read and parse the config files
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<ConfigReade...figReaderInterface|null at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<ConfigReaderInterface>|ConfigReaderInterface|null.
Loading history...
83
     */
84 19
    public function addAppConfig(string $path, string $pathLocal = '', $reader = null): self
85
    {
86 19
        $this->appConfigBuilder->add($path, $pathLocal, $reader);
87
88 19
        return $this;
89
    }
90
91
    /**
92
     * Allow overriding gacela facade suffixes.
93
     */
94 5
    public function addSuffixTypeFacade(string $suffix): self
95
    {
96 5
        $this->suffixTypesBuilder->addFacade($suffix);
97
98 5
        return $this;
99
    }
100
101
    /**
102
     * Allow overriding gacela factory suffixes.
103
     */
104 5
    public function addSuffixTypeFactory(string $suffix): self
105
    {
106 5
        $this->suffixTypesBuilder->addFactory($suffix);
107
108 5
        return $this;
109
    }
110
111
    /**
112
     * Allow overriding gacela config suffixes.
113
     */
114 5
    public function addSuffixTypeConfig(string $suffix): self
115
    {
116 5
        $this->suffixTypesBuilder->addConfig($suffix);
117
118 5
        return $this;
119
    }
120
121
    /**
122
     * Allow overriding gacela dependency provider suffixes.
123
     */
124 6
    public function addSuffixTypeDependencyProvider(string $suffix): self
125
    {
126 6
        $this->suffixTypesBuilder->addDependencyProvider($suffix);
127
128 6
        return $this;
129
    }
130
131
    /**
132
     * @deprecated in favor of `$this->addBinding(key, value)`
133
     * It will be removed in the next release
134
     *
135
     * @param class-string $key
136
     * @param class-string|object|callable $value
137
     */
138 1
    public function addMappingInterface(string $key, string|object|callable $value): self
139
    {
140 1
        return $this->addBinding($key, $value);
141
    }
142
143
    /**
144
     * Bind a key class or interface name to be resolved by Gacela automatically.
145
     *
146
     * @param class-string $key
147
     * @param class-string|object|callable $value
148
     */
149 10
    public function addBinding(string $key, string|object|callable $value): self
150
    {
151 10
        $this->bindingsBuilder->bind($key, $value);
152
153 10
        return $this;
154
    }
155
156
    /**
157
     * Useful to pass services while bootstrapping Gacela to the gacela.php config file.
158
     *
159
     * @param class-string|object|callable $value
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string|object|callable at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string|object|callable.
Loading history...
160
     */
161 3
    public function addExternalService(string $key, $value): self
162
    {
163 3
        $this->externalServices[$key] = $value;
164
165 3
        return $this;
166
    }
167
168
    /**
169
     * Get an external service from its defined key, previously added using `addExternalService()`.
170
     *
171
     * @return class-string|object|callable
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string|object|callable at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string|object|callable.
Loading history...
172
     */
173 4
    public function getExternalService(string $key)
174
    {
175 4
        return $this->externalServices[$key];
176
    }
177
178
    /**
179
     * Enable resetting the memory cache on each setup. Useful for functional tests.
180
     */
181 48
    public function resetInMemoryCache(): self
182
    {
183 48
        $this->shouldResetInMemoryCache = true;
184
185 48
        return $this;
186
    }
187
188
    /**
189
     * Shortcut to setFileCache(true)
190
     */
191 1
    public function enableFileCache(string $dir = null): self
192
    {
193 1
        return $this->setFileCache(true, $dir);
194
    }
195
196
    /**
197
     * Define whether the file cache flag is enabled,
198
     * and the file cache directory.
199
     */
200 16
    public function setFileCache(bool $enabled, string $dir = null): self
201
    {
202 16
        $this->fileCacheEnabled = $enabled;
203 16
        $this->fileCacheDirectory = $dir;
204
205 16
        return $this;
206
    }
207
208
    /**
209
     * Define a list of project namespaces.
210
     *
211
     * @param list<string> $list
212
     */
213 4
    public function setProjectNamespaces(array $list): self
214
    {
215 4
        $this->projectNamespaces = $list;
0 ignored issues
show
Documentation Bug introduced by
It seems like $list of type array is incompatible with the declared type Gacela\Framework\Bootstrap\list of property $projectNamespaces.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
216
217 4
        return $this;
218
    }
219
220
    /**
221
     * Add/replace an existent configuration key with a specific value.
222
     *
223
     * @param mixed $value
224
     */
225 8
    public function addAppConfigKeyValue(string $key, $value): self
226
    {
227 8
        $this->configKeyValues[$key] = $value;
228
229 8
        return $this;
230
    }
231
232
    /**
233
     * Add/replace a list of existent configuration keys with a specific value.
234
     *
235
     * @param array<string, mixed> $config
236
     */
237 2
    public function addAppConfigKeyValues(array $config): self
238
    {
239 2
        $this->configKeyValues = array_merge($this->configKeyValues ?? [], $config);
240
241 2
        return $this;
242
    }
243
244
    /**
245
     * Do not dispatch any event in the application.
246
     */
247 1
    public function disableEventListeners(): self
248
    {
249 1
        $this->areEventListenersEnabled = false;
250
251 1
        return $this;
252
    }
253
254
    /**
255
     * Register a generic listener when any event happens.
256
     * The callable argument must be the type `GacelaEventInterface`.
257
     *
258
     * @param callable(GacelaEventInterface):void $listener
259
     */
260 8
    public function registerGenericListener(callable $listener): self
261
    {
262 8
        $this->genericListeners ??= [];
263 8
        $this->genericListeners[] = $listener;
264
265 8
        return $this;
266
    }
267
268
    /**
269
     * Register a listener when some event happens.
270
     *
271
     * @param class-string $event
272
     * @param callable(GacelaEventInterface):void $listener
273
     */
274 7
    public function registerSpecificListener(string $event, callable $listener): self
275
    {
276 7
        $this->specificListeners[$event] ??= [];
277 7
        $this->specificListeners[$event][] = $listener;
278
279 7
        return $this;
280
    }
281
282 3
    public function extendService(string $id, Closure $service): self
283
    {
284 3
        $this->servicesToExtend[$id] ??= [];
285 3
        $this->servicesToExtend[$id][] = $service;
286
287 3
        return $this;
288
    }
289
290
    /**
291
     * Add a new invokable class that can extend the GacelaConfig object.
292
     *
293
     * This configClass will receive the GacelaConfig object as argument to the __invoke() method.
294
     * ```
295
     * __invoke(GacelaConfig $config): void
296
     * ```
297
     *
298
     * @param class-string $className
299
     */
300 1
    public function extendGacelaConfig(string $className): self
301
    {
302 1
        $this->gacelaConfigsToExtend[] = $className;
303
304 1
        return $this;
305
    }
306
307
    /**
308
     * @param list<class-string> $list
309
     */
310
    public function extendGacelaConfigs(array $list): self
311
    {
312
        $this->gacelaConfigsToExtend = array_merge($this->gacelaConfigsToExtend ?? [], $list);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($this->gacel...tend ?? array(), $list) of type array is incompatible with the declared type Gacela\Framework\Bootstrap\list of property $gacelaConfigsToExtend.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
313
314
        return $this;
315
    }
316
317
    /**
318
     * @param class-string|callable $plugin
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string|callable at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string|callable.
Loading history...
319
     */
320 5
    public function addPlugin(string|callable $plugin): self
321
    {
322 5
        $this->plugins[] = $plugin;
323
324 5
        return $this;
325
    }
326
327
    /**
328
     * @param list<class-string|callable> $list
329
     */
330 1
    public function addPlugins(array $list): self
331
    {
332 1
        $this->plugins = array_merge($this->plugins ?? [], $list);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($this->plugins ?? array(), $list) of type array is incompatible with the declared type Gacela\Framework\Bootstrap\list of property $plugins.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
333
334 1
        return $this;
335
    }
336
337
    /**
338
     * @return array{
339
     *     external-services: array<string,class-string|object|callable>,
340
     *     app-config-builder: AppConfigBuilder,
341
     *     suffix-types-builder: SuffixTypesBuilder,
342
     *     bindings-builder: BindingsBuilder,
343
     *     should-reset-in-memory-cache: ?bool,
344
     *     file-cache-enabled: ?bool,
345
     *     file-cache-directory: ?string,
346
     *     project-namespaces: ?list<string>,
347
     *     config-key-values: ?array<string,mixed>,
348
     *     are-event-listeners-enabled: ?bool,
349
     *     generic-listeners: ?list<callable>,
350
     *     specific-listeners: ?array<class-string,list<callable>>,
351
     *     gacela-configs-to-extend: ?list<class-string>,
352
     *     plugins: ?list<class-string|callable>,
353
     *     instances-to-extend: array<string,list<Closure>>,
354
     * }
355
     *
356
     * @internal
357
     */
358 81
    public function build(): array
359
    {
360 81
        return [
361 81
            'external-services' => $this->externalServices,
362 81
            'app-config-builder' => $this->appConfigBuilder,
363 81
            'suffix-types-builder' => $this->suffixTypesBuilder,
364 81
            'bindings-builder' => $this->bindingsBuilder,
365 81
            'should-reset-in-memory-cache' => $this->shouldResetInMemoryCache,
366 81
            'file-cache-enabled' => $this->fileCacheEnabled,
367 81
            'file-cache-directory' => $this->fileCacheDirectory,
368 81
            'project-namespaces' => $this->projectNamespaces,
369 81
            'config-key-values' => $this->configKeyValues,
370 81
            'are-event-listeners-enabled' => $this->areEventListenersEnabled,
371 81
            'generic-listeners' => $this->genericListeners,
372 81
            'specific-listeners' => $this->specificListeners,
373 81
            'gacela-configs-to-extend' => $this->gacelaConfigsToExtend,
374 81
            'plugins' => $this->plugins,
375 81
            'instances-to-extend' => $this->servicesToExtend,
376 81
        ];
377
    }
378
}
379