1: <?php
2: /**
3: * This file contains the implementation of the interface IEventManager
4: * in the class EventManager for event management.
5: *
6: * @package System
7: *
8: * @author Oleg Schildt
9: */
10:
11: namespace SmartFactory;
12:
13: use \SmartFactory\Interfaces\IEventManager;
14:
15: /**
16: * Class for event management.
17: *
18: * @author Oleg Schildt
19: */
20: class EventManager implements IEventManager
21: {
22: /**
23: * Internal array for storing the event handler mappings.
24: *
25: * @var array
26: *
27: * @see EventManager::addHandler()
28: * @see EventManager::deleteHandler()
29: * @see EventManager::deleteHandlers()
30: * @see EventManager::deleteAllHandlers()
31: *
32: * @author Oleg Schildt
33: */
34: protected static array $event_table = [];
35:
36: /**
37: * Internal array for storing the suspended events.
38: *
39: * @var array
40: *
41: * @see EventManager::suspendEvent()
42: * @see EventManager::resumeEvent()
43: * @see EventManager::resumeAllEvents()
44: *
45: * @author Oleg Schildt
46: */
47: protected static array $suspended_events = [];
48:
49: /**
50: * Adds the handler of an event.
51: *
52: * @param string $event
53: * Event code.
54: *
55: * @param callable $handler
56: * The name or definition of the handler function. The signature of
57: * this function is:
58: *
59: * ```php
60: * function (string $event, array $parameters) : void;
61: * ```
62: *
63: * - $event - the event code.
64: *
65: * - $parameters - parameters passed by the firing of the event.
66: *
67: * @return void
68: *
69: * @throws \Exception
70: * It might throw the following exceptions in the case of any errors:
71: *
72: * - if the event name is not specified.
73: * - if the event handler is not valid.
74: * - if the creation of the handler fails.
75: *
76: * @see EventManager::deleteHandler()
77: * @see EventManager::deleteHandlers()
78: * @see EventManager::deleteAllHandlers()
79: *
80: * @author Oleg Schildt
81: */
82: public function addHandler(string $event, callable $handler): void
83: {
84: if (empty($event)) {
85: throw new \Exception("Event is not specified!");
86: }
87:
88: if (!is_callable($handler, true)) {
89: throw new \Exception("Event handler is not valid!");
90: }
91:
92: $f = new \ReflectionFunction($handler);
93:
94: self::$event_table[$event][$f->__toString()] = $f;
95: } // addEvent
96:
97: /**
98: * Deletes the handler of an event.
99: *
100: * @param string $event
101: * Event code.
102: *
103: * @param callable $handler
104: * The name or definition of the handler function.
105: *
106: * @return void
107: *
108: * @throws \Exception
109: * It might throw the following exceptions in the case of any errors:
110: *
111: * - if the event name is not specified.
112: * - if the event handler is not valid.
113: * - if the creation of the handler fails.
114: *
115: * @see EventManager::addHandler()
116: * @see EventManager::deleteHandlers()
117: * @see EventManager::deleteAllHandlers()
118: *
119: * @author Oleg Schildt
120: */
121: public function deleteHandler(string $event, callable $handler): void
122: {
123: if (empty($event)) {
124: throw new \Exception("Event is not specified!");
125: }
126:
127: if (!is_callable($handler)) {
128: throw new \Exception("Event handler is not valid!");
129: }
130:
131: $f = new \ReflectionFunction($handler);
132:
133: if (isset(self::$event_table[$event][$f->__toString()])) {
134: unset(self::$event_table[$event][$f->__toString()]);
135: }
136: } // deleteEvent
137:
138: /**
139: * Deletes all handlers of an event.
140: *
141: * @param string $event
142: * Event code.
143: *
144: * @return void
145: *
146: * @throws \Exception
147: * It might throw the following exceptions in the case of any errors:
148: *
149: * - if the event name is not specified.
150: *
151: * @see EventManager::addHandler()
152: * @see EventManager::deleteHandler()
153: * @see EventManager::deleteAllHandlers()
154: *
155: * @author Oleg Schildt
156: */
157: public function deleteHandlers(string $event): void
158: {
159: if (empty($event)) {
160: throw new \Exception("Event is not specified!");
161: }
162:
163: if (isset(self::$event_table[$event])) {
164: unset(self::$event_table[$event]);
165: }
166: } // deleteHandlers
167:
168: /**
169: * Deletes all handlers of all events.
170: *
171: * @return void
172: * Returns true if the deletion was successful, otherwise false.
173: *
174: * @see EventManager::addHandler()
175: * @see EventManager::deleteHandler()
176: * @see EventManager::deleteHandlers()
177: *
178: * @author Oleg Schildt
179: */
180: public function deleteAllHandlers(): void
181: {
182: self::$event_table = [];
183: } // deleteAllHandlers
184:
185: /**
186: * Suspends an event.
187: *
188: * If an event is suspended, its handlers are not called when the event is fired.
189: *
190: * @param string $event
191: * Event code.
192: *
193: * @return void
194: *
195: * @throws \Exception
196: * It might throw the following exceptions in the case of any errors:
197: *
198: * - if the event name is not specified.
199: *
200: * @see EventManager::resumeEvent()
201: * @see EventManager::resumeAllEvents()
202: *
203: * @author Oleg Schildt
204: */
205: public function suspendEvent(string $event): void
206: {
207: if (empty($event)) {
208: throw new \Exception("Event is not specified!");
209: }
210:
211: self::$suspended_events[$event] = $event;
212: } // suspendEvent
213:
214: /**
215: * Resumes a previously suspended event.
216: *
217: * @param string $event
218: * Event code.
219: *
220: * @return void
221: *
222: * @throws \Exception
223: * It might throw the following exceptions in the case of any errors:
224: *
225: * - if the event name is not specified.
226: *
227: * @see EventManager::suspendEvent()
228: * @see EventManager::resumeAllEvents()
229: *
230: * @author Oleg Schildt
231: */
232: public function resumeEvent(string $event): void
233: {
234: if (empty($event)) {
235: throw new \Exception("Event is not specified!");
236: }
237:
238: if (isset(self::$suspended_events[$event])) {
239: unset(self::$suspended_events[$event]);
240: }
241: } // resumeEvent
242:
243: /**
244: * Resumes all previously suspended events.
245: *
246: * @return void
247: *
248: * @see EventManager::suspendEvent()
249: * @see EventManager::resumeEvent()
250: *
251: * @author Oleg Schildt
252: */
253: public function resumeAllEvents(): void
254: {
255: self::$suspended_events = [];
256: } // resumeAllEvents
257:
258: /**
259: * Fires and event.
260: *
261: * @param string $event
262: * Event code.
263: *
264: * @param array $parameters
265: * Event code.
266: *
267: * @return int
268: * Returns number of the handlers called for this event.
269: *
270: * @throws \Exception
271: * It might throw the following exceptions in the case of any errors:
272: *
273: * - if the event name is not specified.
274: * - if the creation of the handler fails.
275: *
276: * @author Oleg Schildt
277: */
278: public function fireEvent(string $event, array $parameters): int
279: {
280: if (empty($event)) {
281: throw new \Exception("Event is not specified!");
282: }
283:
284: if (!empty(self::$suspended_events[$event])) {
285: return true;
286: }
287:
288: if (empty(self::$event_table[$event])) {
289: return true;
290: }
291:
292: $cnt = 0;
293:
294: foreach (self::$event_table[$event] as $f) {
295: $cnt++;
296: $f->invoke($event, $parameters);
297: }
298:
299: return $cnt;
300: } // fireEvent
301: } // EventManager