1
|
|
|
<?php |
2
|
|
|
declare(strict_types=1); |
3
|
|
|
|
4
|
|
|
/** |
5
|
|
|
* @Author : a.zinovyev |
6
|
|
|
* @Package: emittr |
7
|
|
|
* @License: http://www.opensource.org/licenses/mit-license.php |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace xobotyi\emittr; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Class EventEmitter |
14
|
|
|
* |
15
|
|
|
* @method static void emit(string $evtName, $payload = null) |
16
|
|
|
* @method static array getEventNames() |
17
|
|
|
* @method static array getListeners(?string $eventName = null) |
18
|
|
|
* @method static int getMaxListeners() |
19
|
|
|
* @method static void on(string $evtName, callable $callback) |
20
|
|
|
* @method static void once(string $evtName, callable $callback) |
21
|
|
|
* @method static void prependListener(string $evtName, callable $callback) |
22
|
|
|
* @method static void prependOnceListener(string $evtName, callable $callback) |
23
|
|
|
* @method static void removeAllListeners(?string $evtName) |
24
|
|
|
* @method static void removeListener(string $evtName, callable $callback) |
25
|
|
|
* @method static void setMaxListeners(int $listenersCount) |
26
|
|
|
* |
27
|
|
|
* @method self emit(string $evtName, $payload = null) |
28
|
|
|
* @method array getEventNames() |
29
|
|
|
* @method array getListeners(?string $eventName = null) |
30
|
|
|
* @method int getMaxListeners() |
31
|
|
|
* @method self on(string $evtName, callable $callback) |
32
|
|
|
* @method self once(string $evtName, callable $callback) |
33
|
|
|
* @method self prependListener(string $evtName, callable $callback) |
34
|
|
|
* @method self prependOnceListener(string $evtName, callable $callback) |
35
|
|
|
* @method self removeAllListeners(?string $evtName) |
36
|
|
|
* @method self removeListener(string $evtName, callable $callback) |
37
|
|
|
* @method self setMaxListeners(int $listenersCount) |
38
|
|
|
* |
39
|
|
|
* @package xobotyi\emittr |
40
|
|
|
*/ |
41
|
|
|
class EventEmitter extends EventEmitterStatic |
42
|
|
|
{ |
43
|
|
|
private $listeners = []; |
44
|
|
|
private $maxListeners = 10; |
45
|
|
|
|
46
|
|
|
public function __call($name, $arguments) { |
47
|
|
|
if (method_exists($this, '_' . $name)) { |
48
|
|
|
return call_user_func_array([$this, '_' . $name], $arguments); |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
throw new \Error('Call to undefined method ' . get_called_class() . '->' . $name . '()'); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
private function _emit(string $evtName, $payload = null) :self { |
55
|
|
|
$calledClass = get_called_class(); |
56
|
|
|
$event = new Event($evtName, $payload, $calledClass, $this); |
57
|
|
|
|
58
|
|
|
if (!$this->listeners || self::propagateEvent($event, $this->listeners)) { |
|
|
|
|
59
|
|
|
if (!(self::$staticListeners[$calledClass] ?? false) || self::propagateEvent($event, self::$staticListeners[$calledClass])) { |
60
|
|
|
EventEmitterGlobal::propagateClassEvent($event); |
61
|
|
|
} |
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
return $this; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
private function _getEventNames() :array { |
68
|
|
|
return \array_keys($this->listeners); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
private function _getListeners(?string $eventName = null) :array { |
72
|
|
|
return $this->listeners[$eventName] ?? []; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
private function _getMaxListeners() :int { |
76
|
|
|
return $this->maxListeners; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
private function _on(string $evtName, callable $callback) :self { |
80
|
|
|
if (($this->listeners[$evtName] ?? false) && $this->maxListeners && count($this->listeners[$evtName]) === $this->maxListeners) { |
81
|
|
|
throw new Exception\EventEmitter("Maximum amount of listeners reached for event " . $evtName . " of " . get_called_class()); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
$this->listeners[$evtName][] = [false, &$callback,]; |
85
|
|
|
|
86
|
|
|
return $this; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
private function _once(string $evtName, callable $callback) :self { |
90
|
|
|
if (($this->listeners[$evtName] ?? false) && $this->maxListeners && count($this->listeners[$evtName]) === $this->maxListeners) { |
91
|
|
|
throw new Exception\EventEmitter("Maximum amount of listeners reached for event " . $evtName . " of " . get_called_class()); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
$this->listeners[$evtName][] = [true, &$callback,]; |
95
|
|
|
|
96
|
|
|
return $this; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
private function _prependListener(string $evtName, callable $callback) :self { |
100
|
|
|
if (($this->listeners[$evtName] ?? false) && $this->maxListeners && count($this->listeners[$evtName]) === $this->maxListeners) { |
101
|
|
|
throw new Exception\EventEmitter("Maximum amount of listeners reached for event " . $evtName . " of " . get_called_class()); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
array_unshift($this->listeners[$evtName], [false, &$callback,]); |
105
|
|
|
|
106
|
|
|
return $this; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
private function _prependOnceListener(string $evtName, callable $callback) :self { |
110
|
|
|
if (($this->listeners[$evtName] ?? false) && $this->maxListeners && count($this->listeners[$evtName]) === $this->maxListeners) { |
111
|
|
|
throw new Exception\EventEmitter("Maximum amount of listeners reached for event " . $evtName . " of " . get_called_class()); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
array_unshift($this->listeners[$evtName], [true, &$callback,]); |
115
|
|
|
|
116
|
|
|
return $this; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
private function _removeAllListeners(?string $evtName) :self { |
120
|
|
|
if ($evtName) { |
121
|
|
|
unset($this->listeners[$evtName]); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
$this->listeners = []; |
125
|
|
|
|
126
|
|
|
return $this; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
private function _removeListener(string $evtName, callable $callback) :self { |
130
|
|
|
if (!($this->listeners[$evtName] ?? false)) { |
131
|
|
|
return $this; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
$this->listeners[$evtName] = array_filter($this->listeners[$evtName], function ($item) use (&$callback) { return $item[1] !== $callback; }); |
135
|
|
|
|
136
|
|
|
if (empty($this->listeners[$evtName])) { |
137
|
|
|
unset($this->listeners[$evtName]); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
return $this; |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
private function _setMaxListeners(int $listenersCount) :self { |
144
|
|
|
if ($listenersCount <= 0) { |
145
|
|
|
throw new \InvalidArgumentException('Listeners count must be greater than 0, got ' . $listenersCount); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
$this->maxListeners = $listenersCount; |
149
|
|
|
|
150
|
|
|
return $this; |
151
|
|
|
} |
152
|
|
|
} |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.