shouldDiscover('events')) { $locator = Services::locator(); $files = $locator->search('Config/Events.php'); } static::$files = $files; foreach (static::$files as $file) { if (is_file($file)) { include $file; } } static::$initialized = true; } //-------------------------------------------------------------------- /** * Registers an action to happen on an event. The action can be any sort * of callable: * * Events::on('create', 'myFunction'); // procedural function * Events::on('create', ['myClass', 'myMethod']); // Class::method * Events::on('create', [$myInstance, 'myMethod']); // Method on an existing instance * Events::on('create', function() {}); // Closure * * @param $event_name * @param callable $callback * @param integer $priority */ public static function on($event_name, $callback, $priority = EVENT_PRIORITY_NORMAL) { if (! isset(static::$listeners[$event_name])) { static::$listeners[$event_name] = [ true, // If there's only 1 item, it's sorted. [$priority], [$callback], ]; } else { static::$listeners[$event_name][0] = false; // Not sorted static::$listeners[$event_name][1][] = $priority; static::$listeners[$event_name][2][] = $callback; } } //-------------------------------------------------------------------- /** * Runs through all subscribed methods running them one at a time, * until either: * a) All subscribers have finished or * b) a method returns false, at which point execution of subscribers stops. * * @param $eventName * @param $arguments * * @return boolean */ public static function trigger($eventName, ...$arguments): bool { // Read in our Config/events file so that we have them all! if (! static::$initialized) { static::initialize(); } $listeners = static::listeners($eventName); foreach ($listeners as $listener) { $start = microtime(true); $result = static::$simulate === false ? call_user_func($listener, ...$arguments) : true; if (CI_DEBUG) { static::$performanceLog[] = [ 'start' => $start, 'end' => microtime(true), 'event' => strtolower($eventName), ]; } if ($result === false) { return false; } } return true; } //-------------------------------------------------------------------- /** * Returns an array of listeners for a single event. They are * sorted by priority. * * If the listener could not be found, returns FALSE, or TRUE if * it was removed. * * @param $event_name * * @return array */ public static function listeners($event_name): array { if (! isset(static::$listeners[$event_name])) { return []; } // The list is not sorted if (! static::$listeners[$event_name][0]) { // Sort it! array_multisort(static::$listeners[$event_name][1], SORT_NUMERIC, static::$listeners[$event_name][2]); // Mark it as sorted already! static::$listeners[$event_name][0] = true; } return static::$listeners[$event_name][2]; } //-------------------------------------------------------------------- /** * Removes a single listener from an event. * * If the listener couldn't be found, returns FALSE, else TRUE if * it was removed. * * @param $event_name * @param callable $listener * * @return boolean */ public static function removeListener($event_name, callable $listener): bool { if (! isset(static::$listeners[$event_name])) { return false; } foreach (static::$listeners[$event_name][2] as $index => $check) { if ($check === $listener) { unset(static::$listeners[$event_name][1][$index]); unset(static::$listeners[$event_name][2][$index]); return true; } } return false; } //-------------------------------------------------------------------- /** * Removes all listeners. * * If the event_name is specified, only listeners for that event will be * removed, otherwise all listeners for all events are removed. * * @param null $event_name */ public static function removeAllListeners($event_name = null) { if (! is_null($event_name)) { unset(static::$listeners[$event_name]); } else { static::$listeners = []; } } //-------------------------------------------------------------------- /** * Sets the path to the file that routes are read from. * * @param array $files */ public static function setFiles(array $files) { static::$files = $files; } //-------------------------------------------------------------------- /** * Returns the files that were found/loaded during this request. * * @return mixed */ public function getFiles() { return static::$files; } //-------------------------------------------------------------------- /** * Turns simulation on or off. When on, events will not be triggered, * simply logged. Useful during testing when you don't actually want * the tests to run. * * @param boolean $choice */ public static function simulate(bool $choice = true) { static::$simulate = $choice; } //-------------------------------------------------------------------- /** * Getter for the performance log records. * * @return array */ public static function getPerformanceLogs() { return static::$performanceLog; } //-------------------------------------------------------------------- }