Completed
Push — master ( e5a3b7...4d7670 )
by Asmir
14s queued 13s
created

EventDispatcher   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 107
Duplicated Lines 0 %

Test Coverage

Coverage 90.38%

Importance

Changes 0
Metric Value
dl 0
loc 107
ccs 47
cts 52
cp 0.9038
rs 10
c 0
b 0
f 0
wmc 29

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getDefaultMethodName() 0 3 1
A setListeners() 0 4 1
B addSubscriber() 0 13 7
D dispatch() 0 26 10
B initializeListeners() 0 15 6
A hasListeners() 0 11 3
A addListener() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
namespace JMS\Serializer\EventDispatcher;
22
23
use JMS\Serializer\Exception\InvalidArgumentException;
24
25
/**
26
 * Light-weight event dispatcher.
27
 *
28
 * This implementation focuses primarily on performance, and dispatching
29
 * events for certain classes. It is not a general purpose event dispatcher.
30
 *
31
 * @author Johannes M. Schmitt <[email protected]>
32
 */
33
class EventDispatcher implements EventDispatcherInterface
34
{
35
    private $listeners = array();
36
    private $classListeners = array();
37
38 3
    public static function getDefaultMethodName($eventName)
39
    {
40 3
        return 'on' . str_replace(array('_', '.'), '', $eventName);
41
    }
42
43
    /**
44
     * Sets the listeners.
45
     *
46
     * @param array $listeners
47
     */
48
    public function setListeners(array $listeners)
49
    {
50
        $this->listeners = $listeners;
51
        $this->classListeners = array();
52
    }
53
54 25
    public function addListener($eventName, $callable, $class = null, $format = null, $interface = null): void
55
    {
56 25
        $this->listeners[$eventName][] = array($callable, $class, $format, $interface);
57 25
        unset($this->classListeners[$eventName]);
58 25
    }
59
60 302
    public function addSubscriber(EventSubscriberInterface $subscriber)
61
    {
62 302
        foreach ($subscriber->getSubscribedEvents() as $eventData) {
63 302
            if (!isset($eventData['event'])) {
64
                throw new InvalidArgumentException(sprintf('Each event must have a "event" key.'));
65
            }
66
67 302
            $method = isset($eventData['method']) ? $eventData['method'] : self::getDefaultMethodName($eventData['event']);
68 302
            $class = isset($eventData['class']) ? $eventData['class'] : null;
69 302
            $format = isset($eventData['format']) ? $eventData['format'] : null;
70 302
            $interface = isset($eventData['interface']) ? $eventData['interface'] : null;
71 302
            $this->listeners[$eventData['event']][] = array(array($subscriber, $method), $class, $format, $interface);
72 302
            unset($this->classListeners[$eventData['event']]);
73
        }
74 302
    }
75
76 212
    public function hasListeners($eventName, $class, $format)
77
    {
78 212
        if (!isset($this->listeners[$eventName])) {
79 184
            return false;
80
        }
81
82 190
        if (!isset($this->classListeners[$eventName][$class][$format])) {
83 190
            $this->classListeners[$eventName][$class][$format] = $this->initializeListeners($eventName, $class, $format);
84
        }
85
86 190
        return !!$this->classListeners[$eventName][$class][$format];
87
    }
88
89 205
    public function dispatch($eventName, $class, $format, Event $event)
90
    {
91 205
        if (!isset($this->listeners[$eventName])) {
92 5
            return;
93
        }
94
95 205
        $object = $event instanceof ObjectEvent ? $event->getObject() : null;
96 205
        $objectClass = $object ? (get_class($object) . $class) : $class;
97
98 205
        if (!isset($this->classListeners[$eventName][$objectClass][$format])) {
99 205
            $this->classListeners[$eventName][$objectClass][$format] = array();
100 205
            foreach ($this->initializeListeners($eventName, $class, $format) as $listener) {
101 205
                if ($listener[3] !== null && !($object instanceof $listener[3])) {
102 190
                    continue;
103
                }
104
105 28
                $this->classListeners[$eventName][$objectClass][$format][] = $listener[0];
106
            }
107
        }
108
109 205
        foreach ($this->classListeners[$eventName][$objectClass][$format] as  $listener) {
110
111 28
            if ($event->isPropagationStopped()) {
112 10
                break;
113
            }
114 28
            \call_user_func($listener, $event, $eventName, $class, $format, $this);
115
        }
116 205
    }
117
118
    /**
119
     * @param string $eventName
120
     * @param string $loweredClass
121
     * @param string $format
122
     *
123
     * @return array An array of listeners
124
     */
125 210
    protected function initializeListeners($eventName, $loweredClass, $format)
126
    {
127 210
        $listeners = array();
128 210
        foreach ($this->listeners[$eventName] as $listener) {
129 210
            if (null !== $listener[1] && $loweredClass !== $listener[1]) {
130 10
                continue;
131
            }
132 210
            if (null !== $listener[2] && $format !== $listener[2]) {
133 3
                continue;
134
            }
135
136 210
            $listeners[] = $listener;
137
        }
138
139 210
        return $listeners;
140
    }
141
}
142
143