Passed
Push — feature/class-resolver-events ( b07999...bba964 )
by Chema
03:27
created

SetupGacela::getEventDispatcher()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5.2

Importance

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

298
                    $this->eventDispatcher->/** @scrutinizer ignore-call */ 
299
                                            registerSpecificListener($event, $callable);

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...
299
                }
300
            }
301
        } else {
302
            $this->eventDispatcher = new NullEventDispatcher();
303
        }
304
305 10
        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...
306
    }
307
308 50
    public function setAreEventListenersEnabled(bool $flag): self
309
    {
310 50
        $this->areEventListenersEnabled = $flag;
311
312 50
        return $this;
313
    }
314
315
    /**
316
     * @param array<string,mixed> $configKeyValues
317
     */
318 50
    private function setConfigKeyValues(array $configKeyValues): self
319
    {
320 50
        $this->configKeyValues = $configKeyValues;
321
322 50
        return $this;
323
    }
324
325
    /**
326
     * @param array<class-string,list<callable>> $listenersPerEvent
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...
327
     */
328 50
    private function setListenersPerEvent(array $listenersPerEvent): self
329
    {
330 50
        $this->listenersPerEvent = $listenersPerEvent;
331
332 50
        return $this;
333
    }
334
}
335