Passed
Push — master ( 339e28...0dda89 )
by Anton
02:55
created

EventEmitter::removeAllListeners()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 14
nc 6
nop 1
dl 0
loc 27
rs 8.439
c 0
b 0
f 0
1
<?php
2
/**
3
 * @Author : a.zinovyev
4
 * @Package: emittr
5
 * @License: http://www.opensource.org/licenses/mit-license.php
6
 */
7
8
namespace xobotyi\emittr;
9
10
class EventEmitter implements Interfaces\EventEmitter
11
{
12
    public const EVENT_LISTENER_ADDED   = 'listenerAdded';
13
    public const EVENT_LISTENER_REMOVED = 'listenerRemoved';
14
15
    /**
16
     * @var Interfaces\EventEmitterGlobal;
17
     */
18
    private $eventEmitterGlobal;
19
20
    private $eventListeners = [];
21
22
    private $maxListenersCount = 10;
23
24
    public function __construct(?Interfaces\EventEmitterGlobal $emitterGlobal = null) {
25
        $this->setGlobalEmitter($emitterGlobal ?: EventEmitterGlobal::getInstance());
26
    }
27
28
    public function emit(string $eventName, $payload = null) :self {
29
        $event = new Event($eventName, $payload, get_called_class(), $this);
30
31
        if (empty($this->eventListeners) || $this->eventEmitterGlobal::propagateEvent($event, $this->eventListeners)) {
32
            $this->eventEmitterGlobal->propagateEventGlobal($event);
33
        }
34
35
        return $this;
36
    }
37
38
    public function on(string $eventName, $callback) :self {
39
        $this->eventEmitterGlobal::storeCallback($this->eventListeners, $eventName, $callback, $this->maxListenersCount, false, false);
40
        $this->emit(self::EVENT_LISTENER_ADDED, ['callback' => &$callback]);
41
42
        return $this;
43
    }
44
45
    public function once(string $eventName, $callback) :self {
46
        $this->eventEmitterGlobal::storeCallback($this->eventListeners, $eventName, $callback, $this->maxListenersCount, true, false);
47
        $this->emit(self::EVENT_LISTENER_ADDED, ['callback' => &$callback]);
48
49
        return $this;
50
    }
51
52
    public function prependListener(string $eventName, $callback) :self {
53
        $this->eventEmitterGlobal::storeCallback($this->eventListeners, $eventName, $callback, $this->maxListenersCount, false, true);
54
        $this->emit(self::EVENT_LISTENER_ADDED, ['callback' => &$callback]);
55
56
        return $this;
57
    }
58
59
    public function prependOnceListener(string $eventName, $callback) :self {
60
        $this->eventEmitterGlobal::storeCallback($this->eventListeners, $eventName, $callback, $this->maxListenersCount, true, true);
61
        $this->emit(self::EVENT_LISTENER_ADDED, ['callback' => &$callback]);
62
63
        return $this;
64
    }
65
66
    public function off(string $eventName, $callback) :self {
67
        if (empty($this->eventListeners[$eventName])) {
68
            return $this;
69
        }
70
71
        $this->eventListeners[$eventName] = \array_values(\array_filter($this->eventListeners[$eventName], function ($item) use (&$callback) { return $item[1] !== $callback; }));
72
        $this->emit(self::EVENT_LISTENER_REMOVED, ['eventName' => $eventName, 'callback' => &$callback]);
73
74
        if (empty($this->eventListeners[$eventName])) {
75
            unset($this->eventListeners[$eventName]);
76
        }
77
78
        return $this;
79
    }
80
81
    public function removeAllListeners(?string $eventName = null) :self {
82
        if ($eventName === null) {
83
            foreach ($this->eventListeners as $eventName => $callbacks) {
84
                foreach ($callbacks as &$callback) {
85
                    $this->emit(self::EVENT_LISTENER_REMOVED, [
86
                        'eventName' => $eventName,
87
                        'callback'  => &$callback[1],
88
                    ]);
89
                }
90
            }
91
92
            $this->eventListeners = [];
93
94
            return $this;
95
        }
96
97
        if (empty($this->eventListeners[$eventName])) {
98
            return $this;
99
        }
100
101
        foreach ($this->eventListeners[$eventName] as $callback) {
102
            $this->emit(self::EVENT_LISTENER_REMOVED, ['eventName' => $eventName, 'callback' => &$callback[1]]);
103
        }
104
105
        unset($this->eventListeners[$eventName]);
106
107
        return $this;
108
    }
109
110
    public function getEventNames() :array {
111
        return empty($this->eventListeners) ? [] : \array_keys($this->eventListeners);
112
    }
113
114
    public function getListeners(?string $eventName = null) :array {
115
        return $eventName ? $this->eventListeners[$eventName] ?? [] : $this->eventListeners;
116
    }
117
118
    public function getMaxListenersCount() :int {
119
        return $this->maxListenersCount;
120
    }
121
122
    public function setMaxListenersCount(int $maxListenersCount) :self {
123
        if ($maxListenersCount < 0) {
124
            throw new \InvalidArgumentException('Listeners count must be greater or equal 0, got ' . $maxListenersCount);
125
        }
126
127
        $this->maxListenersCount = $maxListenersCount;
128
129
        return $this;
130
    }
131
132
    public function getGlobalEmitter() :Interfaces\EventEmitterGlobal {
133
        return $this->eventEmitterGlobal;
134
    }
135
136
    public function setGlobalEmitter(Interfaces\EventEmitterGlobal $emitterGlobal) :self {
137
        $this->eventEmitterGlobal = $emitterGlobal;
138
139
        return $this;
140
    }
141
}