Projekt

Obecné

Profil

Stáhnout (7.03 KB) Statistiky
| Větev: | Revize:
1
<?php
2

    
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

    
12
namespace Symfony\Component\EventDispatcher;
13

    
14
/**
15
 * The EventDispatcherInterface is the central point of Symfony's event listener system.
16
 *
17
 * Listeners are registered on the manager and events are dispatched through the
18
 * manager.
19
 *
20
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
21
 * @author Jonathan Wage <jonwage@gmail.com>
22
 * @author Roman Borschel <roman@code-factory.org>
23
 * @author Bernhard Schussek <bschussek@gmail.com>
24
 * @author Fabien Potencier <fabien@symfony.com>
25
 * @author Jordi Boggiano <j.boggiano@seld.be>
26
 * @author Jordan Alliot <jordan.alliot@gmail.com>
27
 * @author Nicolas Grekas <p@tchwork.com>
28
 */
29
class EventDispatcher implements EventDispatcherInterface
30
{
31
    private $listeners = array();
32
    private $sorted = array();
33

    
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function dispatch($eventName, Event $event = null)
38
    {
39
        if (null === $event) {
40
            $event = new Event();
41
        }
42

    
43
        if ($listeners = $this->getListeners($eventName)) {
44
            $this->doDispatch($listeners, $eventName, $event);
45
        }
46

    
47
        return $event;
48
    }
49

    
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function getListeners($eventName = null)
54
    {
55
        if (null !== $eventName) {
56
            if (empty($this->listeners[$eventName])) {
57
                return array();
58
            }
59

    
60
            if (!isset($this->sorted[$eventName])) {
61
                $this->sortListeners($eventName);
62
            }
63

    
64
            return $this->sorted[$eventName];
65
        }
66

    
67
        foreach ($this->listeners as $eventName => $eventListeners) {
68
            if (!isset($this->sorted[$eventName])) {
69
                $this->sortListeners($eventName);
70
            }
71
        }
72

    
73
        return array_filter($this->sorted);
74
    }
75

    
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function getListenerPriority($eventName, $listener)
80
    {
81
        if (empty($this->listeners[$eventName])) {
82
            return;
83
        }
84

    
85
        if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
86
            $listener[0] = $listener[0]();
87
        }
88

    
89
        foreach ($this->listeners[$eventName] as $priority => $listeners) {
90
            foreach ($listeners as $k => $v) {
91
                if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
92
                    $v[0] = $v[0]();
93
                    $this->listeners[$eventName][$priority][$k] = $v;
94
                }
95
                if ($v === $listener) {
96
                    return $priority;
97
                }
98
            }
99
        }
100
    }
101

    
102
    /**
103
     * {@inheritdoc}
104
     */
105
    public function hasListeners($eventName = null)
106
    {
107
        if (null !== $eventName) {
108
            return !empty($this->listeners[$eventName]);
109
        }
110

    
111
        foreach ($this->listeners as $eventListeners) {
112
            if ($eventListeners) {
113
                return true;
114
            }
115
        }
116

    
117
        return false;
118
    }
119

    
120
    /**
121
     * {@inheritdoc}
122
     */
123
    public function addListener($eventName, $listener, $priority = 0)
124
    {
125
        $this->listeners[$eventName][$priority][] = $listener;
126
        unset($this->sorted[$eventName]);
127
    }
128

    
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function removeListener($eventName, $listener)
133
    {
134
        if (empty($this->listeners[$eventName])) {
135
            return;
136
        }
137

    
138
        if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
139
            $listener[0] = $listener[0]();
140
        }
141

    
142
        foreach ($this->listeners[$eventName] as $priority => $listeners) {
143
            foreach ($listeners as $k => $v) {
144
                if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
145
                    $v[0] = $v[0]();
146
                }
147
                if ($v === $listener) {
148
                    unset($listeners[$k], $this->sorted[$eventName]);
149
                } else {
150
                    $listeners[$k] = $v;
151
                }
152
            }
153

    
154
            if ($listeners) {
155
                $this->listeners[$eventName][$priority] = $listeners;
156
            } else {
157
                unset($this->listeners[$eventName][$priority]);
158
            }
159
        }
160
    }
161

    
162
    /**
163
     * {@inheritdoc}
164
     */
165
    public function addSubscriber(EventSubscriberInterface $subscriber)
166
    {
167
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
168
            if (is_string($params)) {
169
                $this->addListener($eventName, array($subscriber, $params));
170
            } elseif (is_string($params[0])) {
171
                $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
172
            } else {
173
                foreach ($params as $listener) {
174
                    $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
175
                }
176
            }
177
        }
178
    }
179

    
180
    /**
181
     * {@inheritdoc}
182
     */
183
    public function removeSubscriber(EventSubscriberInterface $subscriber)
184
    {
185
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
186
            if (is_array($params) && is_array($params[0])) {
187
                foreach ($params as $listener) {
188
                    $this->removeListener($eventName, array($subscriber, $listener[0]));
189
                }
190
            } else {
191
                $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0]));
192
            }
193
        }
194
    }
195

    
196
    /**
197
     * Triggers the listeners of an event.
198
     *
199
     * This method can be overridden to add functionality that is executed
200
     * for each listener.
201
     *
202
     * @param callable[] $listeners The event listeners
203
     * @param string     $eventName The name of the event to dispatch
204
     * @param Event      $event     The event object to pass to the event handlers/listeners
205
     */
206
    protected function doDispatch($listeners, $eventName, Event $event)
207
    {
208
        foreach ($listeners as $listener) {
209
            if ($event->isPropagationStopped()) {
210
                break;
211
            }
212
            \call_user_func($listener, $event, $eventName, $this);
213
        }
214
    }
215

    
216
    /**
217
     * Sorts the internal list of listeners for the given event by priority.
218
     *
219
     * @param string $eventName The name of the event
220
     */
221
    private function sortListeners($eventName)
222
    {
223
        krsort($this->listeners[$eventName]);
224
        $this->sorted[$eventName] = array();
225

    
226
        foreach ($this->listeners[$eventName] as $priority => $listeners) {
227
            foreach ($listeners as $k => $listener) {
228
                if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
229
                    $listener[0] = $listener[0]();
230
                    $this->listeners[$eventName][$priority][$k] = $listener;
231
                }
232
                $this->sorted[$eventName][] = $listener;
233
            }
234
        }
235
    }
236
}
(5-5/13)