ListenerProvider   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 92
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 27
c 1
b 0
f 0
dl 0
loc 92
rs 10
wmc 7

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A sortedEventCorrelation() 0 42 1
A getListenersForEvent() 0 14 4
A orderedListenerFqcnIterableForEvent() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Th3Mouk\ReactiveEventDispatcher;
6
7
use Psr\Container\ContainerInterface;
8
use Psr\EventDispatcher\ListenerProviderInterface;
9
10
/**
11
 * @psalm-immutable
12
 */
13
final class ListenerProvider implements ListenerProviderInterface
14
{
15
    private ContainerInterface $serviceLocator;
16
    /** @psalm-var array<class-string, list<class-string>> */
17
    private array $sortedCorrelations;
18
19
    /**
20
     * @param array<EventCorrelation> $eventCorrelations
21
     */
22
    public function __construct(ContainerInterface $serviceLocator, array $eventCorrelations)
23
    {
24
        $this->serviceLocator     = $serviceLocator;
25
        $this->sortedCorrelations = $this->sortedEventCorrelation($eventCorrelations);
26
    }
27
28
    /**
29
     * @param array<EventCorrelation> $eventCorrelations
30
     *
31
     * @psalm-return array<class-string, list<class-string>>
32
     */
33
    private function sortedEventCorrelation(array $eventCorrelations): array
34
    {
35
        $sortedWithoutPriorities = array_reduce(
36
            $eventCorrelations,
37
            /**
38
             * @psalm-param array<class-string, array<int, list<class-string>>> $carry
39
             * @psalm-return array<class-string, array<int, list<class-string>>>
40
             */
41
            static function (array $carry, EventCorrelation $eventCorrelation): array {
42
                $carry[$eventCorrelation->eventFqcn][$eventCorrelation->priority->value][] = $eventCorrelation->listenerFqcn;
43
44
                return $carry;
45
            },
46
            []
47
        );
48
49
        /** @psalm-var array<class-string, list<class-string>> $fullySorted */
50
        $fullySorted = array_map(
51
            /**
52
             * @psalm-param array<int, list<class-string>> $eventListenersWithPriorities
53
             * @psalm-return list<class-string>
54
             */
55
            static function (array $eventListenersWithPriorities) {
56
                krsort($eventListenersWithPriorities);
57
58
                return array_reduce(
59
                    $eventListenersWithPriorities,
60
                    /**
61
                     * @psalm-param list<class-string> $carry
62
                     * @psalm-param list<class-string> $listenersSortedByPriorities
63
                     * @psalm-return list<class-string>
64
                     */
65
                    static function (array $carry, array $listenersSortedByPriorities): array {
66
                        return array_merge($carry, $listenersSortedByPriorities);
67
                    },
68
                    []
69
                );
70
            },
71
            $sortedWithoutPriorities
72
        );
73
74
        return $fullySorted;
75
    }
76
77
    /**
78
     * @return iterable<callable>
79
     *
80
     * @inheritDoc
81
     */
82
    public function getListenersForEvent(object $event): iterable
83
    {
84
        foreach ($this->orderedListenerFqcnIterableForEvent($event) as $listenerFqcn) {
85
            if (!$this->serviceLocator->has($listenerFqcn)) {
86
                continue;
87
            }
88
89
            $listener = $this->serviceLocator->get($listenerFqcn);
90
91
            if (!$listener instanceof Listener) {
92
                continue;
93
            }
94
95
            yield [$listener, 'process'];
96
        }
97
    }
98
99
    /**
100
     * @psalm-return array<class-string>
101
     */
102
    private function orderedListenerFqcnIterableForEvent(object $event): array
103
    {
104
        return $this->sortedCorrelations[get_class($event)] ?? [];
105
    }
106
}
107