Passed
Push — master ( fb3de9...9fc5aa )
by Julián
04:52
created

EventHandlerLocator   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 31
c 1
b 0
f 0
dl 0
loc 88
rs 10
wmc 11

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 2
A getHandlers() 0 22 6
A getEventMap() 0 17 3
1
<?php
2
3
/*
4
 * event-symfony-messenger (https://github.com/phpgears/event-symfony-messenger).
5
 * Event bus with Symfony's Messenger.
6
 *
7
 * @license MIT
8
 * @link https://github.com/phpgears/event-symfony-messenger
9
 * @author Julián Gutiérrez <[email protected]>
10
 */
11
12
declare(strict_types=1);
13
14
namespace Gears\Event\Symfony\Messenger;
15
16
use Gears\Event\Event;
17
use Gears\Event\EventHandler;
18
use Gears\Event\Exception\InvalidEventException;
19
use Gears\Event\Exception\InvalidEventHandlerException;
20
use Symfony\Component\Messenger\Envelope;
21
use Symfony\Component\Messenger\Handler\HandlerDescriptor;
22
use Symfony\Component\Messenger\Handler\HandlersLocatorInterface;
23
24
class EventHandlerLocator implements HandlersLocatorInterface
25
{
26
    /**
27
     * Event handlers map.
28
     *
29
     * @var mixed[]
30
     */
31
    protected $handlersMap;
32
33
    /**
34
     * EventHandlerLocator constructor.
35
     *
36
     * @param mixed[] $handlers
37
     */
38
    public function __construct(array $handlers)
39
    {
40
        $handlers = \array_map(
41
            function ($handler) {
42
                if (!\is_array($handler)) {
43
                    $handler = [$handler];
44
                }
45
46
                return $handler;
47
            },
48
            $handlers
49
        );
50
51
        $this->handlersMap = $handlers;
52
    }
53
54
    /**
55
     * {@inheritdoc}
56
     *
57
     * @throws InvalidEventHandlerException
58
     */
59
    public function getHandlers(Envelope $envelope): iterable
60
    {
61
        $seen = [];
62
63
        foreach ($this->getEventMap($envelope) as $type) {
64
            foreach ($this->handlersMap[$type] ?? [] as $alias => $handler) {
65
                if (!$handler instanceof EventHandler) {
66
                    throw new InvalidEventHandlerException(\sprintf(
67
                        'Event handler must implement %s interface, %s given',
68
                        EventHandler::class,
69
                        \is_object($handler) ? \get_class($handler) : \gettype($handler)
70
                    ));
71
                }
72
73
                $handlerCallable = function (Event $event) use ($handler): void {
74
                    $handler->handle($event);
75
                };
76
77
                if (!\in_array($handlerCallable, $seen, true)) {
78
                    $seen[] = $handlerCallable;
79
80
                    yield $alias => new HandlerDescriptor($handlerCallable);
81
                }
82
            }
83
        }
84
    }
85
86
    /**
87
     * Get command mapping.
88
     *
89
     * @param Envelope $envelope
90
     *
91
     * @throws InvalidEventException
92
     *
93
     * @return mixed[]
94
     */
95
    final protected function getEventMap(Envelope $envelope): array
96
    {
97
        /** @var mixed $event */
98
        $event = $envelope->getMessage();
99
100
        if (!$event instanceof Event) {
101
            throw new InvalidEventException(\sprintf(
102
                'Event must implement %s interface, %s given',
103
                Event::class,
104
                \is_object($event) ? \get_class($event) : \gettype($event)
105
            ));
106
        }
107
108
        $class = \get_class($event);
109
110
        return [$class => $class]
111
            + ['*' => '*'];
112
    }
113
}
114