Passed
Push — feature/add-generic-listeners ( 750050...7ef9cb )
by Chema
04:40 queued 03:23
created

SetupGacela   A

Complexity

Total Complexity 38

Size/Duplication

Total Lines 331
Duplicated Lines 0 %

Test Coverage

Coverage 97.37%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 103
dl 0
loc 331
ccs 111
cts 114
cp 0.9737
rs 9.36
c 4
b 0
f 0
wmc 38

29 Methods

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

300
            $this->eventDispatcher->/** @scrutinizer ignore-call */ 
301
                                    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...
301
302 15
            foreach ($this->listenersPerEvent as $event => $listeners) {
303 4
                foreach ($listeners as $callable) {
304 4
                    $this->eventDispatcher->registerSpecificListener($event, $callable);
305
                }
306
            }
307
        } else {
308 1
            $this->eventDispatcher = new NullEventDispatcher();
309
        }
310
311 16
        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\EventLi...ventDispatcherInterface.
Loading history...
312
    }
313
314 55
    public function setAreEventListenersEnabled(bool $flag): self
315
    {
316 55
        $this->areEventListenersEnabled = $flag;
317
318 55
        return $this;
319
    }
320
321
    /**
322
     * @param array<string,mixed> $configKeyValues
323
     */
324 55
    private function setConfigKeyValues(array $configKeyValues): self
325
    {
326 55
        $this->configKeyValues = $configKeyValues;
327
328 55
        return $this;
329
    }
330
331
    /**
332
     * @param list<callable> $listeners
333
     */
334 55
    private function setGenericListeners(array $listeners): self
335
    {
336 55
        $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...
337
338 55
        return $this;
339
    }
340
341
    /**
342
     * @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...
343
     */
344 55
    private function setListenersPerEvent(array $listeners): self
345
    {
346 55
        $this->listenersPerEvent = $listeners;
347
348 55
        return $this;
349
    }
350
}
351