Passed
Push — feature/make-class-name-finder... ( 034803...d97180 )
by Chema
03:32
created

SetupGacela::overrideEventDispatcher()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 9
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 16
rs 9.9666
ccs 9
cts 9
cp 1
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Framework\Bootstrap;
6
7
use Gacela\Framework\ClassResolver\Cache\GacelaFileCache;
8
use Gacela\Framework\Config\GacelaConfigBuilder\ConfigBuilder;
9
use Gacela\Framework\Config\GacelaConfigBuilder\MappingInterfacesBuilder;
10
use Gacela\Framework\Config\GacelaConfigBuilder\SuffixTypesBuilder;
11
use Gacela\Framework\Event\Dispatcher\ConfigurableEventDispatcher;
12
use Gacela\Framework\Event\Dispatcher\EventDispatcherInterface;
13
use Gacela\Framework\Event\Dispatcher\NullEventDispatcher;
14
use RuntimeException;
15
16
use function count;
17
use function is_callable;
18
19
final class SetupGacela extends AbstractSetupGacela
20
{
21
    /** @var callable(ConfigBuilder):void */
22
    private $configFn;
23
24
    /** @var callable(MappingInterfacesBuilder,array<string,mixed>):void */
25
    private $mappingInterfacesFn;
26
27
    /** @var callable(SuffixTypesBuilder):void */
28
    private $suffixTypesFn;
29
30
    /** @var array<string,class-string|object|callable> */
1 ignored issue
show
Documentation Bug introduced by
The doc comment array<string,class-string|object|callable> at position 4 could not be parsed: Unknown type name 'class-string' at position 4 in array<string,class-string|object|callable>.
Loading history...
31
    private array $externalServices = [];
32
33
    private ?ConfigBuilder $configBuilder = null;
34
35
    private ?SuffixTypesBuilder $suffixTypesBuilder = null;
36
37
    private ?MappingInterfacesBuilder $mappingInterfacesBuilder = null;
38
39
    private bool $shouldResetInMemoryCache = false;
40
41
    private bool $fileCacheEnabled = GacelaFileCache::DEFAULT_ENABLED_VALUE;
42
43
    private string $fileCacheDirectory = GacelaFileCache::DEFAULT_DIRECTORY_VALUE;
44
45
    /** @var list<string> */
46
    private array $projectNamespaces = [];
47
48
    /** @var array<string,mixed> */
49
    private array $configKeyValues = [];
50
51
    private bool $areEventListenersEnabled = true;
52
53
    /** @var list<callable> */
54
    private array $genericListeners = [];
55
56
    /** @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...
57
    private array $specificListeners = [];
58
59
    private ?EventDispatcherInterface $eventDispatcher = null;
60
61 88
    public function __construct()
62
    {
63 88
        $this->configFn = static function (): void {
64
        };
65 88
        $this->mappingInterfacesFn = static function (): void {
66
        };
67 88
        $this->suffixTypesFn = static function (): void {
68
        };
69
    }
70
71 10
    public static function fromFile(string $gacelaFilePath): self
72
    {
73 10
        if (!is_file($gacelaFilePath)) {
74
            throw new RuntimeException("Invalid file path: '{$gacelaFilePath}'");
75
        }
76
77
        /** @var callable(GacelaConfig):void|null $setupGacelaFileFn */
78 10
        $setupGacelaFileFn = include $gacelaFilePath;
79 10
        if (!is_callable($setupGacelaFileFn)) {
80
            return new self();
81
        }
82
83 10
        return self::fromCallable($setupGacelaFileFn);
84
    }
85
86
    /**
87
     * @param callable(GacelaConfig):void $setupGacelaFileFn
88
     */
89 49
    public static function fromCallable(callable $setupGacelaFileFn): self
90
    {
91 49
        $gacelaConfig = new GacelaConfig();
92 49
        $setupGacelaFileFn($gacelaConfig);
93
94 49
        return self::fromGacelaConfig($gacelaConfig);
95
    }
96
97 57
    public static function fromGacelaConfig(GacelaConfig $gacelaConfig): self
98
    {
99 57
        $build = $gacelaConfig->build();
100
101 57
        return (new self())
102 57
            ->setConfigBuilder($build['config-builder'])
103 57
            ->setSuffixTypesBuilder($build['suffix-types-builder'])
104 57
            ->setMappingInterfacesBuilder($build['mapping-interfaces-builder'])
105 57
            ->setExternalServices($build['external-services'])
106 57
            ->setShouldResetInMemoryCache($build['should-reset-in-memory-cache'])
107 57
            ->setFileCacheEnabled($build['file-cache-enabled'])
108 57
            ->setFileCacheDirectory($build['file-cache-directory'])
109 57
            ->setProjectNamespaces($build['project-namespaces'])
110 57
            ->setConfigKeyValues($build['config-key-values'])
111 57
            ->setAreEventListenersEnabled($build['are-event-listeners-enabled'])
112 57
            ->setGenericListeners($build['generic-listeners'])
113 57
            ->setSpecificListeners($build['specific-listeners']);
114
    }
115
116 57
    public function setMappingInterfacesBuilder(MappingInterfacesBuilder $builder): self
117
    {
118 57
        $this->mappingInterfacesBuilder = $builder;
119
120 57
        return $this;
121
    }
122
123 57
    public function setSuffixTypesBuilder(SuffixTypesBuilder $builder): self
124
    {
125 57
        $this->suffixTypesBuilder = $builder;
126
127 57
        return $this;
128
    }
129
130 57
    public function setConfigBuilder(ConfigBuilder $builder): self
131
    {
132 57
        $this->configBuilder = $builder;
133
134 57
        return $this;
135
    }
136
137
    /**
138
     * @param callable(ConfigBuilder):void $callable
139
     */
140 3
    public function setConfigFn(callable $callable): self
141
    {
142 3
        $this->configFn = $callable;
143
144 3
        return $this;
145
    }
146
147 88
    public function buildConfig(ConfigBuilder $builder): ConfigBuilder
148
    {
149 88
        if ($this->configBuilder) {
150 57
            $builder = $this->configBuilder;
151
        }
152
153 88
        ($this->configFn)($builder);
154
155 88
        return $builder;
156
    }
157
158
    /**
159
     * @param callable(MappingInterfacesBuilder,array<string,mixed>):void $callable
160
     */
161 3
    public function setMappingInterfacesFn(callable $callable): self
162
    {
163 3
        $this->mappingInterfacesFn = $callable;
164
165 3
        return $this;
166
    }
167
168
    /**
169
     * Define the mapping between interfaces and concretions, so Gacela services will auto-resolve them automatically.
170
     *
171
     * @param array<string,class-string|object|callable> $externalServices
1 ignored issue
show
Documentation Bug introduced by
The doc comment array<string,class-string|object|callable> at position 4 could not be parsed: Unknown type name 'class-string' at position 4 in array<string,class-string|object|callable>.
Loading history...
172
     */
173 88
    public function buildMappingInterfaces(
174
        MappingInterfacesBuilder $builder,
175
        array $externalServices
176
    ): MappingInterfacesBuilder {
177 88
        if ($this->mappingInterfacesBuilder) {
178 57
            $builder = $this->mappingInterfacesBuilder;
179
        }
180
181 88
        ($this->mappingInterfacesFn)(
182
            $builder,
183 88
            array_merge($this->externalServices, $externalServices)
184
        );
185
186 88
        return $builder;
187
    }
188
189
    /**
190
     * @param callable(SuffixTypesBuilder):void $callable
191
     */
192 3
    public function setSuffixTypesFn(callable $callable): self
193
    {
194 3
        $this->suffixTypesFn = $callable;
195
196 3
        return $this;
197
    }
198
199
    /**
200
     * Allow overriding gacela resolvable types.
201
     */
202 88
    public function buildSuffixTypes(SuffixTypesBuilder $builder): SuffixTypesBuilder
203
    {
204 88
        if ($this->suffixTypesBuilder) {
205 57
            $builder = $this->suffixTypesBuilder;
206
        }
207
208 88
        ($this->suffixTypesFn)($builder);
209
210 88
        return $builder;
211
    }
212
213
    /**
214
     * @param array<string,class-string|object|callable> $array
1 ignored issue
show
Documentation Bug introduced by
The doc comment array<string,class-string|object|callable> at position 4 could not be parsed: Unknown type name 'class-string' at position 4 in array<string,class-string|object|callable>.
Loading history...
215
     */
216 60
    public function setExternalServices(array $array): self
217
    {
218 60
        $this->externalServices = $array;
219
220 60
        return $this;
221
    }
222
223
    /**
224
     * @return array<string,class-string|object|callable>
1 ignored issue
show
Documentation Bug introduced by
The doc comment array<string,class-string|object|callable> at position 4 could not be parsed: Unknown type name 'class-string' at position 4 in array<string,class-string|object|callable>.
Loading history...
225
     */
226 18
    public function externalServices(): array
227
    {
228 18
        return $this->externalServices;
229
    }
230
231 57
    public function setShouldResetInMemoryCache(bool $flag): self
232
    {
233 57
        $this->shouldResetInMemoryCache = $flag;
234
235 57
        return $this;
236
    }
237
238 73
    public function shouldResetInMemoryCache(): bool
239
    {
240 73
        return $this->shouldResetInMemoryCache;
241
    }
242
243 57
    public function setFileCacheEnabled(bool $flag): self
244
    {
245 57
        $this->fileCacheEnabled = $flag;
246
247 57
        return $this;
248
    }
249
250 16
    public function isFileCacheEnabled(): bool
251
    {
252 16
        return $this->fileCacheEnabled;
253
    }
254
255 7
    public function getFileCacheDirectory(): string
256
    {
257 7
        return $this->fileCacheDirectory;
258
    }
259
260 57
    public function setFileCacheDirectory(string $dir): self
261
    {
262 57
        $this->fileCacheDirectory = $dir;
263
264 57
        return $this;
265
    }
266
267
    /**
268
     * @param list<string> $list
269
     */
270 57
    public function setProjectNamespaces(array $list): self
271
    {
272 57
        $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...
273
274 57
        return $this;
275
    }
276
277
    /**
278
     * @return list<string>
279
     */
280 21
    public function getProjectNamespaces(): array
281
    {
282 21
        return $this->projectNamespaces;
283
    }
284
285
    /**
286
     * @return array<string,mixed>
287
     */
288 73
    public function getConfigKeyValues(): array
289
    {
290 73
        return $this->configKeyValues;
291
    }
292
293 25
    public function getEventDispatcher(): EventDispatcherInterface
294
    {
295 25
        if ($this->eventDispatcher !== null) {
296 6
            return $this->eventDispatcher;
297
        }
298
299 21
        if ($this->canCreateEventDispatcher()) {
300 7
            $this->eventDispatcher = new ConfigurableEventDispatcher();
301 7
            $this->eventDispatcher->registerGenericListeners($this->genericListeners);
1 ignored issue
show
Bug introduced by
The method registerGenericListeners() 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

301
            $this->eventDispatcher->/** @scrutinizer ignore-call */ 
302
                                    registerGenericListeners($this->genericListeners);

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...
302
303 7
            foreach ($this->specificListeners as $event => $listeners) {
304 4
                foreach ($listeners as $callable) {
305 4
                    $this->eventDispatcher->registerSpecificListener($event, $callable);
306
                }
307
            }
308
        } else {
309 14
            $this->eventDispatcher = new NullEventDispatcher();
310
        }
311
312 21
        return $this->eventDispatcher;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->eventDispatcher returns the type null which is incompatible with the type-hinted return Gacela\Framework\Event\D...ventDispatcherInterface.
Loading history...
313
    }
314
315 57
    public function setAreEventListenersEnabled(bool $flag): self
316
    {
317 57
        $this->areEventListenersEnabled = $flag;
318
319 57
        return $this;
320
    }
321
322 18
    public function overrideEventDispatcher(self $other): self
323
    {
324 18
        if ($other->canCreateEventDispatcher()) {
325 2
            $this->eventDispatcher = new ConfigurableEventDispatcher();
326 2
            $this->eventDispatcher->registerGenericListeners($other->genericListeners);
0 ignored issues
show
Bug introduced by
The method registerGenericListeners() does not exist on Gacela\Framework\Event\D...ventDispatcherInterface. It seems like you code against a sub-type of Gacela\Framework\Event\D...ventDispatcherInterface such as Gacela\Framework\Event\D...igurableEventDispatcher. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

326
            $this->eventDispatcher->/** @scrutinizer ignore-call */ 
327
                                    registerGenericListeners($other->genericListeners);
Loading history...
327
328 2
            foreach ($other->specificListeners as $event => $listeners) {
329 1
                foreach ($listeners as $callable) {
330 1
                    $this->eventDispatcher->registerSpecificListener($event, $callable);
0 ignored issues
show
Bug introduced by
The method registerSpecificListener() does not exist on Gacela\Framework\Event\D...ventDispatcherInterface. It seems like you code against a sub-type of Gacela\Framework\Event\D...ventDispatcherInterface such as Gacela\Framework\Event\D...igurableEventDispatcher. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

330
                    $this->eventDispatcher->/** @scrutinizer ignore-call */ 
331
                                            registerSpecificListener($event, $callable);
Loading history...
331
                }
332
            }
333
        } else {
334 16
            $this->eventDispatcher = new NullEventDispatcher();
335
        }
336
337 18
        return $this;
338
    }
339
340 37
    private function canCreateEventDispatcher(): bool
341
    {
342 37
        return $this->areEventListenersEnabled
343 37
            && $this->hasEventListeners();
344
    }
345
346 37
    private function hasEventListeners(): bool
347
    {
348 37
        return count($this->genericListeners) > 0
349 37
            || count($this->specificListeners) > 0;
350
    }
351
352
    /**
353
     * @param array<string,mixed> $configKeyValues
354
     */
355 57
    private function setConfigKeyValues(array $configKeyValues): self
356
    {
357 57
        $this->configKeyValues = $configKeyValues;
358
359 57
        return $this;
360
    }
361
362
    /**
363
     * @param list<callable> $listeners
364
     */
365 57
    private function setGenericListeners(array $listeners): self
366
    {
367 57
        $this->genericListeners = $listeners;
0 ignored issues
show
Documentation Bug introduced by
It seems like $listeners of type array is incompatible with the declared type Gacela\Framework\Bootstrap\list of property $genericListeners.

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...
368
369 57
        return $this;
370
    }
371
372
    /**
373
     * @param array<class-string,list<callable>> $listeners
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...
374
     */
375 57
    private function setSpecificListeners(array $listeners): self
376
    {
377 57
        $this->specificListeners = $listeners;
378
379 57
        return $this;
380
    }
381
}
382