Passed
Push — master ( dfe2d2...d6a9e4 )
by Anton
02:18
created

EventEmitter::_emit()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 6
nc 3
nop 2
dl 0
loc 11
rs 8.8571
c 0
b 0
f 0
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)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->listeners of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
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
}