Passed
Pull Request — master (#1316)
by Alexander
02:53
created

EventDispatcher::getListeners()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1.125

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 1
cts 2
cp 0.5
crap 1.125
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace JMS\Serializer\EventDispatcher;
6
7
use JMS\Serializer\Exception\InvalidArgumentException;
8
9
/**
10
 * Light-weight event dispatcher.
11
 *
12
 * This implementation focuses primarily on performance, and dispatching
13
 * events for certain classes. It is not a general purpose event dispatcher.
14
 *
15
 * @author Johannes M. Schmitt <[email protected]>
16
 */
17
class EventDispatcher implements EventDispatcherInterface
18
{
19
    /**
20
     * @var array
21
     */
22 3
    private $listeners = [];
23
24 3
    /**
25
     * ClassListeners cache
26
     *
27
     * @var array
28
     */
29
    private $classListeners = [];
30
31
    public static function getDefaultMethodName(string $eventName): string
32
    {
33
        return 'on' . str_replace(['_', '.'], '', $eventName);
34
    }
35
36
    /**
37
     * Sets the listeners.
38 25
     *
39
     * @param array $listeners
40 25
     */
41 25
    public function setListeners(array $listeners): void
42 25
    {
43
        $this->listeners = $listeners;
44 342
        $this->classListeners = [];
45
    }
46 342
47 342
    public function getListeners(): array
48
    {
49
        return $this->listeners;
50
    }
51 342
52 342
    /**
53 342
     * {@inheritdoc}
54 342
     */
55 342
    public function addListener(string $eventName, $callable, ?string $class = null, ?string $format = null, ?string $interface = null): void
56 342
    {
57
        $this->listeners[$eventName][] = [$callable, $class, $format, $interface];
58 342
        unset($this->classListeners[$eventName]);
59
    }
60 229
61
    public function addSubscriber(EventSubscriberInterface $subscriber): void
62 229
    {
63 197
        foreach ($subscriber->getSubscribedEvents() as $eventData) {
64
            if (!isset($eventData['event'])) {
65
                throw new InvalidArgumentException(sprintf('Each event must have a "event" key.'));
66 210
            }
67 210
68
            $method = $eventData['method'] ?? self::getDefaultMethodName($eventData['event']);
69
            $class = $eventData['class'] ?? null;
70 210
            $format = $eventData['format'] ?? null;
71
            $interface = $eventData['interface'] ?? null;
72
            $this->listeners[$eventData['event']][] = [[$subscriber, $method], $class, $format, $interface];
73 225
            unset($this->classListeners[$eventData['event']]);
74
        }
75 225
    }
76 5
77
    public function hasListeners(string $eventName, string $class, string $format): bool
78
    {
79 225
        if (!isset($this->listeners[$eventName])) {
80 225
            return false;
81 225
        }
82
83 225
        if (!isset($this->classListeners[$eventName][$class][$format])) {
84 35
            $this->classListeners[$eventName][$class][$format] = $this->initializeListeners($eventName, $class, $format);
85
        }
86
87 225
        return !!$this->classListeners[$eventName][$class][$format];
88
    }
89 225
90 210
    public function dispatch(string $eventName, string $class, string $format, Event $event): void
91
    {
92
        if (!isset($this->listeners[$eventName])) {
93 28
            return;
94
        }
95 28
96 28
        $object = $event instanceof ObjectEvent ? $event->getObject() : null;
97
        $realClass = is_object($object) ? get_class($object) : '';
98
        $objectClass = $realClass !== $class ? $realClass . $class : $class;
99 225
100
        if (!isset($this->classListeners[$eventName][$objectClass][$format])) {
101
            $this->classListeners[$eventName][$objectClass][$format] = $this->initializeListeners($eventName, $class, $format);
102
        }
103
104
        foreach ($this->classListeners[$eventName][$objectClass][$format] as $listener) {
105
            if (!empty($listener[3]) && !($object instanceof $listener[3])) {
106
                continue;
107
            }
108 230
109
            \call_user_func($listener[0], $event, $eventName, $class, $format, $this);
110 230
111 230
            if ($event->isPropagationStopped()) {
112 230
                break;
113 10
            }
114
        }
115 230
    }
116 3
117
    /**
118
     * @return array An array of listeners
119 230
     */
120
    protected function initializeListeners(string $eventName, string $loweredClass, string $format): array
121
    {
122 230
        $listeners = [];
123
        foreach ($this->listeners[$eventName] as $listener) {
124
            if (null !== $listener[1] && $loweredClass !== $listener[1]) {
125
                continue;
126
            }
127
128
            if (null !== $listener[2] && $format !== $listener[2]) {
129
                continue;
130
            }
131
132
            $listeners[] = $listener;
133
        }
134
135
        return $listeners;
136
    }
137
}
138