GacelaConfig::extendGacelaConfigs()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Framework\Bootstrap;
6
7
use Closure;
8
use Gacela\Framework\Bootstrap\Setup\GacelaConfigTransfer;
9
use Gacela\Framework\Config\ConfigReaderInterface;
10
use Gacela\Framework\Config\GacelaConfigBuilder\AppConfigBuilder;
11
use Gacela\Framework\Config\GacelaConfigBuilder\BindingsBuilder;
12
use Gacela\Framework\Config\GacelaConfigBuilder\SuffixTypesBuilder;
13
use Gacela\Framework\Event\GacelaEventInterface;
14
15
final class GacelaConfig
16
{
17
    private readonly AppConfigBuilder $appConfigBuilder;
18
19
    private readonly SuffixTypesBuilder $suffixTypesBuilder;
20
21
    private readonly BindingsBuilder $bindingsBuilder;
22
23
    private ?bool $shouldResetInMemoryCache = null;
24
25
    private ?bool $fileCacheEnabled = null;
26
27
    private ?string $fileCacheDirectory = null;
28
29
    /** @var list<string> */
30
    private ?array $projectNamespaces = null;
31
32
    /** @var array<string,mixed> */
33
    private ?array $configKeyValues = null;
34
35
    private ?bool $areEventListenersEnabled = null;
36
37
    /** @var list<callable> */
38
    private ?array $genericListeners = null;
39
40
    /** @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...
41
    private ?array $specificListeners = null;
42
43
    /** @var list<class-string> */
44
    private ?array $gacelaConfigsToExtend = null;
45
46
    /** @var list<class-string|callable> */
47
    private ?array $plugins = null;
48
49
    /** @var array<string,list<Closure>> */
50
    private array $servicesToExtend = [];
51
52
    /** @var array<string,Closure> */
53
    private array $factories = [];
54
55
    /**
56
     * @param array<string,class-string|object|callable> $externalServices
57
     */
58 94
    public function __construct(private array $externalServices = [])
59
    {
60 94
        $this->appConfigBuilder = new AppConfigBuilder();
0 ignored issues
show
Bug introduced by
The property appConfigBuilder is declared read-only in Gacela\Framework\Bootstrap\GacelaConfig.
Loading history...
61 94
        $this->suffixTypesBuilder = new SuffixTypesBuilder();
0 ignored issues
show
Bug introduced by
The property suffixTypesBuilder is declared read-only in Gacela\Framework\Bootstrap\GacelaConfig.
Loading history...
62 94
        $this->bindingsBuilder = new BindingsBuilder();
0 ignored issues
show
Bug introduced by
The property bindingsBuilder is declared read-only in Gacela\Framework\Bootstrap\GacelaConfig.
Loading history...
63 94
    }
64
65
    /**
66
     * Define 'config/*.php' as path, and 'config/local.php' as local path for the configuration.
67
     *
68
     * @codeCoverageIgnore
69
     *
70
     * @return Closure(GacelaConfig):void
71
     */
72
    public static function defaultPhpConfig(): callable
73
    {
74
        return static function (self $config): void {
75
            $config->addAppConfig('config/*.php', 'config/local.php');
76
        };
77
    }
78
79
    /**
80
     * Define the path where the configuration will be stored.
81
     *
82
     * @param string $path define the path where Gacela will read all the config files
83
     * @param string $pathLocal define the path where Gacela will read the local config file
84
     * @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...
85
     */
86
    public function addAppConfig(string $path, string $pathLocal = '', string|ConfigReaderInterface|null $reader = null): self
87 20
    {
88
        $this->appConfigBuilder->add($path, $pathLocal, $reader);
89 20
90
        return $this;
91 20
    }
92
93
    /**
94
     * Allow overriding gacela facade suffixes.
95
     */
96
    public function addSuffixTypeFacade(string $suffix): self
97 5
    {
98
        $this->suffixTypesBuilder->addFacade($suffix);
99 5
100
        return $this;
101 5
    }
102
103
    /**
104
     * Allow overriding gacela factory suffixes.
105
     */
106
    public function addSuffixTypeFactory(string $suffix): self
107 5
    {
108
        $this->suffixTypesBuilder->addFactory($suffix);
109 5
110
        return $this;
111 5
    }
112
113
    /**
114
     * Allow overriding gacela config suffixes.
115
     */
116
    public function addSuffixTypeConfig(string $suffix): self
117 5
    {
118
        $this->suffixTypesBuilder->addConfig($suffix);
119 5
120
        return $this;
121 5
    }
122
123
    /**
124
     * Allow overriding gacela dependency provider suffixes.
125
     */
126
    public function addSuffixTypeProvider(string $suffix): self
127 6
    {
128
        $this->suffixTypesBuilder->addProvider($suffix);
129 6
130
        return $this;
131 6
    }
132
133
    /**
134
     * @deprecated in favor of `$this->addBinding(key, value)`
135
     * It will be removed in the next release
136
     *
137
     * @param class-string $key
138
     * @param class-string|object|callable $value
139
     */
140
    public function addMappingInterface(string $key, string|object|callable $value): self
141 1
    {
142
        return $this->addBinding($key, $value);
143 1
    }
144
145
    /**
146
     * Bind a key class or interface name to be resolved by Gacela automatically.
147
     *
148
     * @param class-string $key
149
     * @param class-string|object|callable $value
150
     */
151
    public function addBinding(string $key, string|object|callable $value): self
152 11
    {
153
        $this->bindingsBuilder->bind($key, $value);
154 11
155
        return $this;
156 11
    }
157
158
    /**
159
     * Useful to pass services while bootstrapping Gacela to the gacela.php config file.
160
     *
161
     * @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...
162
     */
163
    public function addExternalService(string $key, $value): self
164 3
    {
165
        $this->externalServices[$key] = $value;
166 3
167
        return $this;
168 3
    }
169
170
    /**
171
     * Get an external service from its defined key, previously added using `addExternalService()`.
172
     *
173
     * @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...
174
     */
175
    public function getExternalService(string $key)
176 4
    {
177
        return $this->externalServices[$key];
178 4
    }
179
180
    /**
181
     * Enable resetting the memory cache on each setup. Useful for functional tests.
182
     */
183
    public function resetInMemoryCache(): self
184 59
    {
185
        $this->shouldResetInMemoryCache = true;
186 59
187
        return $this;
188 59
    }
189
190
    /**
191
     * Shortcut to setFileCache(true)
192
     */
193
    public function enableFileCache(?string $dir = null): self
194 2
    {
195
        return $this->setFileCache(true, $dir);
196 2
    }
197
198
    /**
199
     * Define whether the file cache flag is enabled,
200
     * and the file cache directory.
201
     */
202
    public function setFileCache(bool $enabled, ?string $dir = null): self
203 17
    {
204
        $this->fileCacheEnabled = $enabled;
205 17
        $this->fileCacheDirectory = $dir;
206 17
207
        return $this;
208 17
    }
209
210
    /**
211
     * Define a list of project namespaces.
212
     *
213
     * @param list<string> $list
214
     */
215
    public function setProjectNamespaces(array $list): self
216 4
    {
217
        $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...
218 4
219
        return $this;
220 4
    }
221
222
    /**
223
     * Add/replace an existent configuration key with a specific value.
224
     */
225
    public function addAppConfigKeyValue(string $key, mixed $value): self
226
    {
227
        $this->configKeyValues[$key] = $value;
228 8
229
        return $this;
230 8
    }
231
232 8
    /**
233
     * Add/replace a list of existent configuration keys with a specific value.
234
     *
235
     * @param array<string, mixed> $config
236
     */
237
    public function addAppConfigKeyValues(array $config): self
238
    {
239
        $this->configKeyValues = array_merge($this->configKeyValues ?? [], $config);
240 2
241
        return $this;
242 2
    }
243
244 2
    /**
245
     * Do not dispatch any event in the application.
246
     */
247
    public function disableEventListeners(): self
248
    {
249
        $this->areEventListenersEnabled = false;
250 1
251
        return $this;
252 1
    }
253
254 1
    /**
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
    public function registerGenericListener(callable $listener): self
261
    {
262
        $this->genericListeners ??= [];
263 11
        $this->genericListeners[] = $listener;
264
265 11
        return $this;
266 11
    }
267
268 11
    /**
269
     * Register a listener when some event happens.
270
     *
271
     * @param class-string $event
272
     * @param callable(GacelaEventInterface):void $listener
273
     */
274
    public function registerSpecificListener(string $event, callable $listener): self
275
    {
276
        $this->specificListeners[$event] ??= [];
277 7
        $this->specificListeners[$event][] = $listener;
278
279 7
        return $this;
280 7
    }
281
282 7
    public function extendService(string $id, Closure $service): self
283
    {
284
        $this->servicesToExtend[$id] ??= [];
285 3
        $this->servicesToExtend[$id][] = $service;
286
287 3
        return $this;
288 3
    }
289
290 3
    /**
291
     * Register a factory service that creates a new instance on each call.
292
     * Unlike regular services (which are singletons), factory services return
293
     * a new instance every time they are resolved from the container.
294
     *
295
     * @param string $id The service identifier (usually a class name or interface)
296
     * @param Closure $factory The factory closure that creates the service instance
297
     *
298
     * @return $this
299
     */
300
    public function addFactory(string $id, Closure $factory): self
301
    {
302
        $this->factories[$id] = $factory;
303 2
304
        return $this;
305 2
    }
306
307 2
    /**
308
     * Add a new invokable class that can extend the GacelaConfig object.
309
     *
310
     * This configClass will receive the GacelaConfig object as argument to the __invoke() method.
311
     * ```
312
     * __invoke(GacelaConfig $config): void
313 2
     * ```
314
     *
315 2
     * @param class-string $className
316
     */
317 2
    public function extendGacelaConfig(string $className): self
318
    {
319
        $this->gacelaConfigsToExtend[] = $className;
320
321
        return $this;
322
    }
323 5
324
    /**
325 5
     * @param list<class-string> $list
326
     */
327 5
    public function extendGacelaConfigs(array $list): self
328
    {
329
        $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...
330
331
        return $this;
332
    }
333 1
334
    /**
335 1
     * @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...
336
     */
337 1
    public function addPlugin(string|callable $plugin): self
338
    {
339
        $this->plugins[] = $plugin;
340
341
        return $this;
342
    }
343 93
344
    /**
345 93
     * @param list<class-string|callable> $list
346 93
     */
347 93
    public function addPlugins(array $list): self
348 93
    {
349 93
        $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...
350 93
351 93
        return $this;
352 93
    }
353 93
354 93
    /**
355 93
     * @internal
356 93
     */
357 93
    public function toTransfer(): GacelaConfigTransfer
358 93
    {
359 93
        return new GacelaConfigTransfer(
360 93
            $this->appConfigBuilder,
361 93
            $this->suffixTypesBuilder,
362
            $this->bindingsBuilder,
363
            $this->externalServices,
364
            $this->shouldResetInMemoryCache,
365
            $this->fileCacheEnabled,
366
            $this->fileCacheDirectory,
367
            $this->projectNamespaces,
368
            $this->configKeyValues,
369
            $this->genericListeners,
370
            $this->specificListeners,
371
            $this->areEventListenersEnabled,
372
            $this->gacelaConfigsToExtend,
373
            $this->plugins,
374
            $this->servicesToExtend,
375
            $this->factories,
376
        );
377
    }
378
}
379