-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEventManagerTrait.php
170 lines (139 loc) · 4.46 KB
/
EventManagerTrait.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
<?php
namespace Phug;
use Phug\Event\ListenerQueue;
trait EventManagerTrait
{
/**
* @var ListenerQueue[]
*/
private $eventListeners = [];
/**
* Returns current event listeners by event name.
*
* @return ListenerQueue[]
*/
public function getEventListeners()
{
return $this->eventListeners;
}
/**
* Merge current events listeners with a given list.
*
* @param ListenerQueue[]|EventManagerInterface $eventListeners event listeners by event name
*
* @return bool true on success false on failure
*/
public function mergeEventListeners($eventListeners)
{
if ($eventListeners instanceof EventManagerInterface) {
$eventListeners = $eventListeners->getEventListeners();
}
foreach (((array) $eventListeners) as $eventName => $listeners) {
$queue = [];
if (isset($this->eventListeners[$eventName])) {
$innerListeners = clone $this->eventListeners[$eventName];
$innerListeners->setExtractFlags(ListenerQueue::EXTR_DATA);
foreach ($innerListeners as $callback) {
$queue[] = $callback;
}
}
$listeners = clone $listeners;
$listeners->setExtractFlags(ListenerQueue::EXTR_BOTH);
foreach ($listeners as $listener) {
if (!in_array($listener['data'], $queue, true)) {
$this->attach($eventName, $listener['data'], $listener['priority']);
}
}
}
return true;
}
/**
* Attaches a listener to an event.
*
* @param string $event the event to attach too
* @param callable $callback a callable function
* @param int $priority the priority at which the $callback executed
*
* @return bool true on success false on failure
*/
public function attach($event, $callback, $priority = 0)
{
if (!isset($this->eventListeners[$event])) {
$this->clearListeners($event);
}
$this->eventListeners[$event]->insert($callback, $priority);
return true;
}
/**
* Detaches a listener from an event.
*
* @param string $event the event to attach too
* @param callable $callback a callable function
*
* @return bool true on success false on failure
*/
public function detach($event, $callback)
{
if (!isset($this->eventListeners[$event]) || $this->eventListeners[$event]->isEmpty()) {
return false;
}
$removed = false;
$listeners = $this->eventListeners[$event];
$newListeners = new ListenerQueue();
$listeners->setExtractFlags(ListenerQueue::EXTR_BOTH);
foreach ($listeners as $item) {
if ($item['data'] === $callback) {
$removed = true;
continue;
}
$newListeners->insert($item['data'], $item['priority']);
}
$listeners->setExtractFlags(ListenerQueue::EXTR_DATA);
$this->eventListeners[$event] = $newListeners;
return $removed;
}
/**
* Clear all listeners for a given event.
*
* @param string $event
*
* @return void
*/
public function clearListeners($event)
{
$this->eventListeners[$event] = new ListenerQueue();
}
/**
* Trigger an event.
*
* Can accept an EventInterface or will create one if not passed
*
* @param string|EventInterface $event
* @param object|string $target
* @param array|object $argv
*
* @return mixed
*/
public function trigger($event, $target = null, $argv = [])
{
$event = $event instanceof EventInterface
? $event
: new Event($event);
$event->setTarget($target ?: $this);
$event->setParams($argv);
$eventName = $event->getName();
if (!isset($this->eventListeners[$eventName]) || $this->eventListeners[$eventName]->isEmpty()) {
return null;
}
$listeners = clone $this->eventListeners[$eventName];
$listeners->setExtractFlags(ListenerQueue::EXTR_DATA);
$result = null;
foreach ($listeners as $callback) {
$result = call_user_func($callback, $event);
if ($event->isPropagationStopped()) {
return $result;
}
}
return $result;
}
}