Test Setup Failed
Push — main ( abdcb9...2e5f68 )
by Slawomir
04:37
created

ApplicationEventSubscriber   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 68
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
c 1
b 0
f 0
dl 0
loc 68
rs 10
wmc 6

4 Methods

Rating   Name   Duplication   Size   Complexity  
A matchHandlers() 0 9 1
A __invoke() 0 16 3
A __construct() 0 5 1
A invokeHandler() 0 9 1
1
<?php
2
3
namespace App\Infrastructure\Events\Api;
4
5
use App\Infrastructure\Events\ApplicationOutboundEvent;
6
use App\Infrastructure\Events\EventIdHolder;
7
use DusanKasan\Knapsack\Collection;
8
use Psr\Log\LoggerInterface;
9
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
10
11
/**
12
 * This is a base for all Services that want to listen to the Events published by other Applications/Modules.
13
 * It's based on Symfony Messenger and uses the subscribe() method to match the incoming Events to the Handlers.
14
 */
15
abstract class ApplicationEventSubscriber implements MessageHandlerInterface
16
{
17
18
    private Collection $subscribedHandlers;
19
20
    public function __construct(
21
        private LoggerInterface $logger
22
    )
23
    {
24
        $this->subscribedHandlers = Collection::from($this->subscribe());
25
    }
26
27
28
    /**
29
     * @param ApplicationOutboundEvent $event
30
     */
31
    public function __invoke(ApplicationOutboundEvent $event)
32
    {
33
        EventIdHolder::set($event->getEventId());
34
        $this->logger->info(sprintf("[event]: Received Outbound Event %s(%s)", $event::class, $event));
35
        foreach ($this->matchHandlers($event) as $handler) {
36
            try {
37
                $this->invokeHandler($handler, $event);
38
            } catch (\Throwable $e) {
39
                $this->logger->error(sprintf("[event]: Exception caught when handling an Outbound Event '%s(%s)':%s",
40
                        $event::class, json_encode($event->getData()), $e->getMessage())
41
                );
42
                $this->logger->error($e->getTraceAsString());
43
            }
44
45
        }
46
        EventIdHolder::clear();
47
    }
48
49
    /**
50
     * @param ApplicationOutboundEvent $event
51
     * @return array<EventHandlerReference>
52
     */
53
    private function matchHandlers(ApplicationOutboundEvent $event): array
54
    {
55
        return $this
56
            ->subscribedHandlers
57
            ->filter(function ($value, $key) use ($event) {
58
                return $key == $event->getName();
59
            })->map(function ($value, $key) {
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

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

59
            })->map(function ($value, /** @scrutinizer ignore-unused */ $key) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
60
                return $value;
61
            })->toArray();
62
    }
63
64
    /**
65
     * @return array<string, EventHandlerReference>
66
     */
67
    protected abstract function subscribe(): array;
68
69
    /**
70
     * @param EventHandlerReference $handler
71
     * @param ApplicationOutboundEvent $event
72
     * @throws \ReflectionException
73
     */
74
    public function invokeHandler(EventHandlerReference $handler, ApplicationOutboundEvent $event): void
75
    {
76
        $handlerMethod = new \ReflectionMethod($this, $handler->getHandlerMethodName());
77
        $className = $handler->getInboundEventClass();
78
        $inboundEvent = new $className($event->getData());
79
        $this->logger->info(sprintf("[event]: Calling Event Subscriber %s:%s for Inbound Event %s(%s)",
80
            $this::class, $handlerMethod->name, $event::class, $event
81
        ));
82
        $handlerMethod->getClosure($this)($inboundEvent);
83
    }
84
}