SetupGacela::getFileCacheDirectory()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Framework\Bootstrap;
6
7
use Closure;
8
use Gacela\Framework\Bootstrap\Setup\GacelaConfigExtender;
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\Dispatcher\EventDispatcherInterface;
13
use RuntimeException;
14
15
use function array_unique;
16
use function is_callable;
17
use function sprintf;
18
19
/**
20
 * @psalm-suppress ArgumentTypeCoercion,MixedArgumentTypeCoercion
21
 */
22
final class SetupGacela extends AbstractSetupGacela
23
{
24
    /** @var callable(AppConfigBuilder):void */
25
    private $appConfigFn;
26
27
    /** @var callable(BindingsBuilder,array<string,mixed>):void */
28
    private $bindingsFn;
29
30
    /** @var callable(SuffixTypesBuilder):void */
31
    private $suffixTypesFn;
32
33
    /** @var ?array<string,class-string|object|callable> */
34
    private ?array $externalServices = null;
35
36
    private ?AppConfigBuilder $appConfigBuilder = null;
37
38
    private ?SuffixTypesBuilder $suffixTypesBuilder = null;
39
40
    private ?BindingsBuilder $bindingsBuilder = null;
41
42
    private ?bool $shouldResetInMemoryCache = null;
43
44
    private ?bool $fileCacheEnabled = null;
45
46
    private ?string $fileCacheDirectory = null;
47
48
    /** @var ?list<string> */
49
    private ?array $projectNamespaces = null;
50
51
    /** @var ?array<string,mixed> */
52
    private ?array $configKeyValues = null;
53
54
    private ?bool $areEventListenersEnabled = null;
55
56
    /** @var ?list<callable> */
57
    private ?array $genericListeners = null;
58
59
    /** @var ?array<class-string,list<callable>> */
60
    private ?array $specificListeners = null;
61
62
    private ?EventDispatcherInterface $eventDispatcher = null;
63
64
    /** @var ?array<string,bool> */
65
    private ?array $changedProperties = null;
66
67
    /** @var ?array<string,list<Closure>> */
68
    private ?array $servicesToExtend = null;
69
70
    /** @var ?list<class-string> */
71
    private ?array $gacelaConfigsToExtend = null;
72
73
    /** @var ?list<class-string|callable> */
74
    private ?array $plugins = null;
75 133
76
    public function __construct()
77 133
    {
78 74
        $emptyFn = static function (): void {};
79
80 133
        $this->appConfigFn = $emptyFn;
81 133
        $this->bindingsFn = $emptyFn;
82 133
        $this->suffixTypesFn = $emptyFn;
83
    }
84
85
    /**
86
     * @codeCoverageIgnore
87
     */
88
    public static function fromFile(string $gacelaFilePath): self
89
    {
90
        if (!is_file($gacelaFilePath)) {
91
            throw new RuntimeException(sprintf("Invalid file path: '%s'", $gacelaFilePath));
92
        }
93
94
        /** @var callable(GacelaConfig):void|null $setupGacelaFileFn */
95
        $setupGacelaFileFn = include $gacelaFilePath;
96
        if (!is_callable($setupGacelaFileFn)) {
97
            return new self();
98
        }
99
100
        return self::fromCallable($setupGacelaFileFn);
101
    }
102
103
    /**
104
     * @param callable(GacelaConfig):void $setupGacelaFileFn
105
     */
106 74
    public static function fromCallable(callable $setupGacelaFileFn): self
107
    {
108 74
        $gacelaConfig = new GacelaConfig();
109 74
        $setupGacelaFileFn($gacelaConfig);
110
111 74
        return self::fromGacelaConfig($gacelaConfig);
112
    }
113
114 93
    public static function fromGacelaConfig(GacelaConfig $gacelaConfig): self
115
    {
116 93
        (new GacelaConfigExtender())->extend($gacelaConfig);
117
118 93
        $dto = $gacelaConfig->toTransfer();
119
120 93
        return (new self())
121 93
            ->setExternalServices($dto->externalServices)
122 93
            ->setAppConfigBuilder($dto->appConfigBuilder)
123 93
            ->setSuffixTypesBuilder($dto->suffixTypesBuilder)
124 93
            ->setBindingsBuilder($dto->bindingsBuilder)
125 93
            ->setShouldResetInMemoryCache($dto->shouldResetInMemoryCache)
126 93
            ->setFileCacheEnabled($dto->fileCacheEnabled)
127 93
            ->setFileCacheDirectory($dto->fileCacheDirectory)
128 93
            ->setProjectNamespaces($dto->projectNamespaces)
129 93
            ->setConfigKeyValues($dto->configKeyValues)
130 93
            ->setAreEventListenersEnabled($dto->areEventListenersEnabled)
131 93
            ->setGenericListeners($dto->genericListeners)
132 93
            ->setSpecificListeners($dto->specificListeners)
133 93
            ->setGacelaConfigsToExtend($dto->gacelaConfigsToExtend)
134 93
            ->setPlugins($dto->plugins)
135 93
            ->setServicesToExtend($dto->servicesToExtend);
136
    }
137
138
    /**
139
     * @param array<string,class-string|object|callable> $array
140
     */
141 96
    public function setExternalServices(?array $array): self
142
    {
143 96
        $this->markPropertyChanged(self::externalServices, true);
144 96
        $this->externalServices = $array;
145
146 96
        return $this;
147
    }
148
149 93
    public function setAppConfigBuilder(AppConfigBuilder $builder): self
150
    {
151 93
        $this->appConfigBuilder = $builder;
152
153 93
        return $this;
154
    }
155
156 93
    public function setSuffixTypesBuilder(SuffixTypesBuilder $builder): self
157
    {
158 93
        $this->suffixTypesBuilder = $builder;
159
160 93
        return $this;
161
    }
162
163 93
    public function setBindingsBuilder(BindingsBuilder $builder): self
164
    {
165 93
        $this->bindingsBuilder = $builder;
166
167 93
        return $this;
168
    }
169
170
    /**
171
     * @param callable(AppConfigBuilder):void $callable
172
     */
173 3
    public function setAppConfigFn(callable $callable): self
174
    {
175 3
        $this->appConfigFn = $callable;
176
177 3
        return $this;
178
    }
179
180 75
    public function buildAppConfig(AppConfigBuilder $builder): AppConfigBuilder
181
    {
182 75
        $builder = parent::buildAppConfig($builder);
183
184 75
        if ($this->appConfigBuilder instanceof AppConfigBuilder) {
185 67
            $builder = $this->appConfigBuilder;
186
        }
187
188 75
        ($this->appConfigFn)($builder);
189
190 75
        return $builder;
191
    }
192
193
    /**
194
     * @param callable(BindingsBuilder,array<string,mixed>):void $callable
195
     */
196 3
    public function setBindingsFn(callable $callable): self
197
    {
198 3
        $this->bindingsFn = $callable;
199
200 3
        return $this;
201
    }
202
203
    /**
204
     * Define the mapping between interfaces and concretions, so Gacela services will auto-resolve them automatically.
205
     *
206
     * @param array<string,class-string|object|callable> $externalServices
207
     */
208 75
    public function buildBindings(
209
        BindingsBuilder $builder,
210
        array $externalServices,
211
    ): BindingsBuilder {
212 75
        $builder = parent::buildBindings($builder, $externalServices);
213
214 75
        if ($this->bindingsBuilder instanceof BindingsBuilder) {
215 67
            $builder = $this->bindingsBuilder;
216
        }
217
218 75
        ($this->bindingsFn)(
219 75
            $builder,
220 75
            array_merge($this->externalServices ?? [], $externalServices)
221 75
        );
222
223 75
        return $builder;
224
    }
225
226
    /**
227
     * @param callable(SuffixTypesBuilder):void $callable
228
     */
229 3
    public function setSuffixTypesFn(callable $callable): self
230
    {
231 3
        $this->suffixTypesFn = $callable;
232
233 3
        return $this;
234
    }
235
236
    /**
237
     * Allow overriding gacela resolvable types.
238
     */
239 75
    public function buildSuffixTypes(SuffixTypesBuilder $builder): SuffixTypesBuilder
240
    {
241 75
        $builder = parent::buildSuffixTypes($builder);
242
243 75
        if ($this->suffixTypesBuilder instanceof SuffixTypesBuilder) {
244 67
            $builder = $this->suffixTypesBuilder;
245
        }
246
247 75
        ($this->suffixTypesFn)($builder);
248
249 75
        return $builder;
250
    }
251
252
    /**
253
     * @return array<string, class-string|object|callable>
254
     */
255 29
    public function externalServices(): array
256
    {
257 29
        return array_merge(
258 29
            parent::externalServices(),
259 29
            $this->externalServices ?? [],
260 29
        );
261
    }
262
263 93
    public function setShouldResetInMemoryCache(?bool $flag): self
264
    {
265 93
        $this->markPropertyChanged(self::shouldResetInMemoryCache, $flag);
266 93
        $this->shouldResetInMemoryCache = $flag ?? self::DEFAULT_SHOULD_RESET_IN_MEMORY_CACHE;
267
268 93
        return $this;
269
    }
270
271 107
    public function shouldResetInMemoryCache(): bool
272
    {
273 107
        return (bool)$this->shouldResetInMemoryCache;
274
    }
275
276 49
    public function isFileCacheEnabled(): bool
277
    {
278 49
        return (bool)$this->fileCacheEnabled;
279
    }
280
281 7
    public function getFileCacheDirectory(): string
282
    {
283 7
        return (string)$this->fileCacheDirectory;
284
    }
285
286 93
    public function setFileCacheDirectory(?string $dir): self
287
    {
288 93
        $this->markPropertyChanged(self::fileCacheDirectory, $dir);
289 93
        $this->fileCacheDirectory = $dir ?? self::DEFAULT_FILE_CACHE_DIRECTORY;
290
291 93
        return $this;
292
    }
293
294
    /**
295
     * @param ?list<string> $list
296
     */
297 93
    public function setProjectNamespaces(?array $list): self
298
    {
299 93
        $this->markPropertyChanged(self::projectNamespaces, $list);
300 93
        $this->projectNamespaces = $list ?? self::DEFAULT_PROJECT_NAMESPACES;
301
302 93
        return $this;
303
    }
304
305
    /**
306
     * @return list<string>
307
     */
308 45
    public function getProjectNamespaces(): array
309
    {
310 45
        return (array)$this->projectNamespaces;
311
    }
312
313
    /**
314
     * @return array<string,mixed>
315
     */
316 107
    public function getConfigKeyValues(): array
317
    {
318 107
        return (array)$this->configKeyValues;
319
    }
320
321 70
    public function getEventDispatcher(): EventDispatcherInterface
322
    {
323 70
        return $this->eventDispatcher ??= SetupEventDispatcher::getDispatcher($this);
324
    }
325
326
    /**
327
     * @return array<string,list<Closure>>
328
     */
329 120
    public function getServicesToExtend(): array
330
    {
331 120
        return (array)$this->servicesToExtend;
332
    }
333
334 93
    public function setFileCacheEnabled(?bool $flag): self
335
    {
336 93
        $this->markPropertyChanged(self::fileCacheEnabled, $flag);
337 93
        $this->fileCacheEnabled = $flag ?? self::DEFAULT_FILE_CACHE_ENABLED;
338
339 93
        return $this;
340
    }
341
342 70
    public function canCreateEventDispatcher(): bool
343
    {
344 70
        return $this->areEventListenersEnabled === true
345 70
            && $this->hasEventListeners();
346
    }
347
348
    /**
349
     * @param ?array<string,mixed> $configKeyValues
350
     */
351 93
    public function setConfigKeyValues(?array $configKeyValues): self
352
    {
353 93
        $this->markPropertyChanged(self::configKeyValues, $configKeyValues);
354 93
        $this->configKeyValues = $configKeyValues ?? self::DEFAULT_CONFIG_KEY_VALUES;
355
356 93
        return $this;
357
    }
358
359
    /**
360
     * @return array<class-string,list<callable>>|null
361
     */
362 16
    public function getSpecificListeners(): ?array
363
    {
364 16
        return $this->specificListeners;
365
    }
366
367
    /**
368
     * @return list<callable>|null
369
     */
370 16
    public function getGenericListeners(): ?array
371
    {
372 16
        return $this->genericListeners;
373
    }
374
375 29
    public function isPropertyChanged(string $name): bool
376
    {
377 29
        return $this->changedProperties[$name] ?? false;
378
    }
379
380 29
    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): self
381
    {
382 29
        $this->eventDispatcher = $eventDispatcher;
383
384 29
        return $this;
385
    }
386
387 29
    public function combine(self $other): self
388
    {
389 29
        return (new SetupCombinator($this))->combine($other);
390
    }
391
392
    /**
393
     * @param list<Closure> $servicesToExtend
394
     */
395 1
    public function addServicesToExtend(string $serviceId, array $servicesToExtend): self
396
    {
397 1
        $this->servicesToExtend[$serviceId] ??= [];
398 1
        $this->servicesToExtend[$serviceId] = [...$this->servicesToExtend[$serviceId], ...$servicesToExtend];
399 1
400 1
        return $this;
401 1
    }
402
403 1
    /**
404
     * @param array<string,class-string|object|callable> $list
405
     */
406 29
    public function combineExternalServices(array $list): void
407
    {
408 29
        $this->setExternalServices(array_merge($this->externalServices ?? [], $list));
409
    }
410
411 1
    /**
412
     * @param list<string> $list
413 1
     */
414
    public function combineProjectNamespaces(array $list): void
415
    {
416 1
        $this->setProjectNamespaces(array_merge($this->projectNamespaces ?? [], $list));
417
    }
418 1
419
    /**
420
     * @param array<string,mixed> $list
421
     */
422
    public function combineConfigKeyValues(array $list): void
423
    {
424 1
        $this->setConfigKeyValues(array_merge($this->configKeyValues ?? [], $list));
425
    }
426 1
427 1
    /**
428 1
     * @param list<class-string> $list
429
     */
430
    public function combineGacelaConfigsToExtend(array $list): void
431
    {
432
        $this->setGacelaConfigsToExtend(
433
            // @phpstan-ignore-next-line
434 1
            array_unique(array_merge($this->gacelaConfigsToExtend ?? [], $list)),
435
        );
436 1
    }
437
438
    /**
439
     * @param list<class-string|callable> $list
440
     */
441
    public function combinePlugins(array $list): void
442 1
    {
443
        $this->setPlugins(array_merge($this->plugins ?? [], $list));
444 1
    }
445
446
    /**
447
     * @return list<class-string>
448
     */
449
    public function getGacelaConfigsToExtend(): array
450 107
    {
451
        return (array)$this->gacelaConfigsToExtend;
452 107
    }
453
454
    /**
455 93
     * @return list<class-string|callable>
456
     */
457 93
    public function getPlugins(): array
458
    {
459 93
        return (array)$this->plugins;
460
    }
461
462 70
    private function setAreEventListenersEnabled(?bool $flag): self
463
    {
464 70
        $this->areEventListenersEnabled = $flag ?? self::DEFAULT_ARE_EVENT_LISTENERS_ENABLED;
465 70
466
        return $this;
467
    }
468
469
    private function hasEventListeners(): bool
470
    {
471 93
        return ($this->genericListeners !== null && $this->genericListeners !== [])
472
            || ($this->specificListeners !== null && $this->specificListeners !== []);
473 93
    }
474
475 93
    /**
476
     * @param ?list<callable> $listeners
477
     */
478
    private function setGenericListeners(?array $listeners): self
479
    {
480
        $this->genericListeners = $listeners ?? self::DEFAULT_GENERIC_LISTENERS;
481 93
482
        return $this;
483 93
    }
484 93
485
    /**
486 93
     * @param ?array<string,list<Closure>> $list
487
     */
488
    private function setServicesToExtend(?array $list): self
489
    {
490
        $this->markPropertyChanged(self::servicesToExtend, $list);
491
        $this->servicesToExtend = $list ?? self::DEFAULT_SERVICES_TO_EXTEND;
492 93
493
        return $this;
494 93
    }
495 93
496
    /**
497 93
     * @param ?list<class-string> $list
498
     */
499
    private function setGacelaConfigsToExtend(?array $list): self
500
    {
501
        $this->markPropertyChanged(self::gacelaConfigsToExtend, $list);
502
        $this->gacelaConfigsToExtend = $list ?? self::DEFAULT_GACELA_CONFIGS_TO_EXTEND;
503 93
504
        return $this;
505 93
    }
506 93
507
    /**
508 93
     * @param ?list<class-string|callable> $list
509
     */
510
    private function setPlugins(?array $list): self
511
    {
512
        $this->markPropertyChanged(self::plugins, $list);
513
        $this->plugins = $list ?? self::DEFAULT_PLUGINS;
514 93
515
        return $this;
516 93
    }
517
518 93
    /**
519
     * @param ?array<class-string,list<callable>> $listeners
520
     */
521 96
    private function setSpecificListeners(?array $listeners): self
522
    {
523 96
        $this->specificListeners = $listeners ?? self::DEFAULT_SPECIFIC_LISTENERS;
524
525
        return $this;
526
    }
527
528
    /**
529
     * @param (Closure[]|callable|class-string|mixed)[]|bool|null|string $value
0 ignored issues
show
Documentation Bug introduced by
The doc comment (Closure[]|callable|clas...xed)[]|bool|null|string at position 7 could not be parsed: Unknown type name 'class-string' at position 7 in (Closure[]|callable|class-string|mixed)[]|bool|null|string.
Loading history...
530
     *
531
     * @psalm-param array<int<0, max>|string, callable|class-string|list<Closure>|mixed>|bool|null|string $value
532
     */
533
    private function markPropertyChanged(string $name, array|bool|string|null $value): void
534
    {
535
        $this->changedProperties[$name] = ($value !== null);
536
    }
537
}
538