Dispatcher::getListeners()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 4
nop 0
1
<?php
2
/**
3
 * Veto.
4
 * PHP Microframework.
5
 *
6
 * @author Damien Walsh <[email protected]>
7
 * @copyright Damien Walsh 2013-2014
8
 * @version 0.1
9
 * @package veto
10
 */
11
namespace Veto\Event;
12
13
/**
14
 * The Veto Event Dispatcher.
15
 *
16
 * Implements an event dispatcher with deferred priority sorting.
17
 */
18
class Dispatcher
19
{
20
    /**
21
     * The registered listeners for this Event Dispatcher
22
     *
23
     * @var array
24
     */
25
    private $listeners = array();
26
27
    /**
28
     * An associative array mapping each event name to the flag indicating if sorting is required
29
     *
30
     * @var array
31
     */
32
    private $sortingRequiredFlags = array();
33
34
    /**
35
     * Register a listener with this event dispatcher.
36
     *
37
     * @param string $eventName The name of the event to listen for
38
     * @param callable $callable The callable to dispatch events to
39
     * @param int $priority Optional priority for the listener. Lower is higher.
40
     * @throws \InvalidArgumentException
41
     */
42
    public function listen($eventName, $callable, $priority = 0)
43
    {
44
        if (!is_callable($callable)) {
45
            throw new \InvalidArgumentException(
46
                'Veto\Event\Dispatcher::listen() - $callable must be a callable value'
47
            );
48
        }
49
50
        $this->listeners[$eventName][$priority][] = $callable;
51
        $this->sortingRequiredFlags[$eventName] = true;
52
    }
53
54
    /**
55
     * Dispatches an event to any associated listeners.
56
     *
57
     * @param Event $event
58
     * @return int The number of listeners fired
59
     */
60
    public function dispatch($eventName, Event $event)
61
    {
62
        if (isset($this->listeners[$eventName])) {
63
64
            // Does the list need to be priority-sorted?
65
            if ($this->sortingRequiredFlags[$eventName]) {
66
                $this->sortListeners($eventName);
67
            }
68
69
            foreach ($this->listeners[$eventName] as $priorityGroup) {
70
                foreach ($priorityGroup as $listener) {
71
                    // Pass the event, the name and this dispatcher instance
72
                    call_user_func($listener, $event, $eventName, $this);
73
74
                    // If the propagation was stopped, do not dispatch to any more listeners
75
                    if ($event->isPropagationStopped()) {
76
                        break;
77
                    }
78
                }
79
            }
80
        }
81
    }
82
83
    /**
84
     * Return the registered listeners for each event name
85
     */
86
    public function getListeners()
87
    {
88
        $listeners = array();
89
90
        foreach ($this->listeners as $eventName => $priorities) {
91
            foreach ($priorities as $priority => $priorityGroup) {
92
                foreach ($priorityGroup as $eventListener) {
93
                    $listeners[$eventName][] = $eventListener;
94
                }
95
            }
96
        }
97
98
        return $listeners;
99
    }
100
101
    /**
102
     * Sort the internal representation of the listener list for an event name.
103
     *
104
     * @param string $eventName
105
     */
106
    private function sortListeners($eventName)
107
    {
108
        ksort($this->listeners[$eventName]);
109
        $this->sortingRequiredFlags[$eventName] = false;
110
    }
111
}
112