EventRouterMap::get()   B
last analyzed

Complexity

Conditions 7
Paths 16

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 14
c 0
b 0
f 0
nc 16
nop 1
dl 0
loc 29
ccs 15
cts 15
cp 1
crap 7
rs 8.8333
1
<?php
2
3
namespace Smoren\EventRouter\Components;
4
5
use Smoren\EventRouter\Interfaces\EventConfigInterface;
6
use Smoren\EventRouter\Interfaces\EventInterface;
7
8
/**
9
 * Map for storing event route rules
10
 */
11
class EventRouterMap
12
{
13
    /**
14
     * @var array<string, array<array{EventConfigInterface, callable}>>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, array<arra...gInterface, callable}>> at position 8 could not be parsed: Expected ':' at position 8, but found 'EventConfigInterface'.
Loading history...
15
     * [origin => [[config, handler], ...], ...]
16
     */
17
    protected array $originMap = [];
18
    /**
19
     * @var array<string, array<string, array<array{EventConfigInterface, callable}>>>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, array<stri...Interface, callable}>>> at position 12 could not be parsed: Expected ':' at position 12, but found 'EventConfigInterface'.
Loading history...
20
     * [origin => [name => [[config, handler], ...], ...], ...]
21
     */
22
    protected array $originNameMap = [];
23
24
    /**
25
     * Adds new event router rule to map
26
     * @param EventConfigInterface $config
27
     * @param callable $handler
28
     * @return void
29
     */
30 11
    public function add(EventConfigInterface $config, callable $handler): void
31
    {
32 11
        [$origin, $name] = [$config->getOrigin(), $config->getName()];
33
34 11
        if($name === null) {
35 11
            if(!isset($this->originMap[$origin])) {
36 11
                $this->originNameMap[$origin] = [];
37
            }
38 11
            $this->originMap[$origin][] = [$config, $handler];
39
        } else {
40 5
            if(!isset($this->originNameMap[$origin])) {
41 1
                $this->originNameMap[$origin] = [];
42
            }
43 5
            if(!isset($this->originNameMap[$origin][$name])) {
44 5
                $this->originNameMap[$origin][$name] = [];
45
            }
46 5
            $this->originNameMap[$origin][$name][] = [$config, $handler];
47
        }
48
    }
49
50
    /**
51
     * Returns suitable handlers from map for event
52
     * @param EventInterface $event
53
     * @return callable[]
54
     */
55 11
    public function get(EventInterface $event): array
56
    {
57 11
        $handlers = [];
58
59
        /**
60
         * @var EventConfigInterface $config
61
         * @var callable $handler
62
         */
63 11
        foreach($this->originMap[$event->getOrigin()] ?? [] as [$config, $handler]) {
64 10
            if(!$this->hasRecipientsIntersection($config, $event)) {
65 1
                continue;
66
            }
67 10
            if(!$this->applyExtraFilter($config, $event)) {
68 1
                continue;
69
            }
70 10
            $handlers[] = $handler;
71
        }
72
73 11
        foreach($this->originNameMap[$event->getOrigin()][$event->getName()] ?? [] as [$config, $handler]) {
74 5
            if(!$this->hasRecipientsIntersection($config, $event)) {
75 1
                continue;
76
            }
77 5
            if(!$this->applyExtraFilter($config, $event)) {
78 1
                continue;
79
            }
80 5
            $handlers[] = $handler;
81
        }
82
83 11
        return $handlers;
84
    }
85
86
    /**
87
     * Returns true if config condition and event have intersection by recipients
88
     * @param EventConfigInterface $config route config condition
89
     * @param EventInterface $event event
90
     * @return bool
91
     */
92 11
    protected function hasRecipientsIntersection(EventConfigInterface $config, EventInterface $event): bool
93
    {
94 11
        $candidates = $config->getRecipients();
95
96 11
        if($candidates === null) {
97 10
            return true;
98
        }
99
100 1
        $recipients = $event->getRecipients();
101
102 1
        return (bool)count(array_intersect($candidates, $recipients));
103
    }
104
105
    /**
106
     * Returns result of extra filter call for event
107
     * @param EventConfigInterface $config route config condition
108
     * @param EventInterface $event event
109
     * @return bool
110
     */
111 11
    protected function applyExtraFilter(EventConfigInterface $config, EventInterface $event): bool
112
    {
113 11
        return ($filter = $config->getExtraFilter()) === null || $filter($event);
114
    }
115
}
116