Passed
Pull Request — master (#1111)
by Aleksei
10:58
created

EventsBootloader   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Test Coverage

Coverage 97.37%

Importance

Changes 0
Metric Value
wmc 11
eloc 35
c 0
b 0
f 0
dl 0
loc 99
ccs 37
cts 38
cp 0.9737
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 9 1
A __construct() 0 3 1
A boot() 0 26 5
A addInterceptor() 0 4 1
A autowire() 0 6 1
A initEventDispatcher() 0 15 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Spiral\Events\Bootloader;
6
7
use Psr\Container\ContainerExceptionInterface;
8
use Psr\Container\ContainerInterface;
9
use Psr\EventDispatcher\EventDispatcherInterface;
10
use Spiral\Boot\AbstractKernel;
11
use Spiral\Boot\Bootloader\Bootloader;
12
use Spiral\Boot\FinalizerInterface;
13
use Spiral\Bootloader\Attributes\AttributesBootloader;
14
use Spiral\Config\ConfiguratorInterface;
15
use Spiral\Config\Patch\Append;
16
use Spiral\Core\CompatiblePipelineBuilder;
17
use Spiral\Core\Container;
18
use Spiral\Core\Container\Autowire;
19
use Spiral\Core\CoreInterceptorInterface;
20
use Spiral\Core\FactoryInterface;
21
use Spiral\Events\AutowireListenerFactory;
22
use Spiral\Events\Config\EventsConfig;
23
use Spiral\Events\EventDispatcher;
24
use Spiral\Events\EventDispatcherAwareInterface;
25
use Spiral\Events\Interceptor\Core;
26
use Spiral\Events\ListenerFactoryInterface;
27
use Spiral\Events\ListenerProcessorRegistry;
28
use Spiral\Events\Processor\AttributeProcessor;
29
use Spiral\Events\Processor\ConfigProcessor;
30
use Spiral\Events\Processor\ProcessorInterface;
31
use Spiral\Interceptors\InterceptorInterface;
32
use Spiral\Tokenizer\Bootloader\TokenizerListenerBootloader;
33
34
/**
35
 * @psalm-import-type TInterceptor from EventsConfig
36
 */
37
final class EventsBootloader extends Bootloader
38
{
39
    protected const DEPENDENCIES = [
40
        TokenizerListenerBootloader::class,
41
        AttributesBootloader::class,
42
    ];
43
44
    protected const SINGLETONS = [
45
        ListenerFactoryInterface::class => AutowireListenerFactory::class,
46
        ListenerProcessorRegistry::class => ListenerProcessorRegistry::class,
47
    ];
48
49 357
    public function __construct(
50
        private readonly ConfiguratorInterface $configs
51
    ) {
52 357
    }
53
54 357
    public function init(): void
55
    {
56 357
        $this->configs->setDefaults(EventsConfig::CONFIG, [
57 357
            'listeners' => [],
58 357
            'processors' => [
59 357
                AttributeProcessor::class,
60 357
                ConfigProcessor::class,
61 357
            ],
62 357
            'interceptors' => [],
63 357
        ]);
64
    }
65
66 357
    public function boot(
67
        Container $container,
68
        FactoryInterface $factory,
69
        EventsConfig $config,
70
        AbstractKernel $kernel,
71
        ListenerProcessorRegistry $registry,
72
        FinalizerInterface $finalizer,
73
        ?EventDispatcherInterface $eventDispatcher = null
74
    ): void {
75 357
        if ($eventDispatcher !== null) {
76 6
            $this->initEventDispatcher(new Core($eventDispatcher), $config, $container, $factory);
77
        }
78
79 357
        foreach ($config->getProcessors() as $processor) {
80 357
            $processor = $this->autowire($processor, $container, $factory);
81
82 357
            \assert($processor instanceof ProcessorInterface);
83 357
            $registry->addProcessor($processor);
84
        }
85
86 357
        $kernel->bootstrapped(static function () use ($registry): void {
87 357
            $registry->process();
88 357
        });
89
90 357
        if ($finalizer instanceof EventDispatcherAwareInterface && $eventDispatcher !== null) {
91 2
            $finalizer->setEventDispatcher($eventDispatcher);
92
        }
93
    }
94
95
    /**
96
     * @param TInterceptor $interceptor
0 ignored issues
show
Bug introduced by
The type Spiral\Events\Bootloader\TInterceptor was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
97
     */
98 1
    public function addInterceptor(
99
        string|InterceptorInterface|CoreInterceptorInterface|Container\Autowire $interceptor,
100
    ): void {
101 1
        $this->configs->modify(EventsConfig::CONFIG, new Append('interceptors', null, $interceptor));
102
    }
103
104 6
    private function initEventDispatcher(
105
        Core $core,
106
        EventsConfig $config,
107
        Container $container,
108
        FactoryInterface $factory
109
    ): void {
110 6
        $builder = new CompatiblePipelineBuilder();
0 ignored issues
show
Deprecated Code introduced by
The class Spiral\Core\CompatiblePipelineBuilder has been deprecated: Use {@see PipelineBuilder} instead. ( Ignorable by Annotation )

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

110
        $builder = /** @scrutinizer ignore-deprecated */ new CompatiblePipelineBuilder();
Loading history...
111 6
        $list = [];
112 6
        foreach ($config->getInterceptors() as $interceptor) {
113
            $list[] = $this->autowire($interceptor, $container, $factory);
114
        }
115
116 6
        $pipeline = $builder->withInterceptors(...$list)->build($core);
117 6
        $container->removeBinding(EventDispatcherInterface::class);
118 6
        $container->bindSingleton(EventDispatcherInterface::class, new EventDispatcher($pipeline));
119
    }
120
121
    /**
122
     * @template T of object
123
     *
124
     * @param class-string<T>|Autowire<T>|T $id
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<T>|Autowire<T>|T at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<T>|Autowire<T>|T.
Loading history...
125
     *
126
     * @return T
127
     *
128
     * @throws ContainerExceptionInterface
129
     */
130 357
    private function autowire(string|object $id, ContainerInterface $container, FactoryInterface $factory): object
131
    {
132 357
        return match (true) {
133 357
            \is_string($id) => $container->get($id),
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type object; however, parameter $id of Psr\Container\ContainerInterface::get() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

133
            \is_string($id) => $container->get(/** @scrutinizer ignore-type */ $id),
Loading history...
134 357
            $id instanceof Autowire => $id->resolve($factory),
135 357
            default => $id,
136 357
        };
137
    }
138
}
139