Source Code: SmartFactory/EventManager.php

  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