enable_emoji) $this->priorities["markup_text"][] = array( "priority" => 10, "function" => "emote" ); if ($config->enable_markdown) $this->priorities["markup_text"][] = array( "priority" => 5, "function" => "markdown" ); } /** * Function: cmp * Sorts actions by priority when used with usort. */ private function cmp($a, $b): int { if (empty($a) or empty($b)) return 0; if ($a["priority"] == $b["priority"]) return 0; return ($a["priority"] < $b["priority"]) ? -1 : 1 ; } /** * Function: decide * Decides what to do with a call return value. */ private function decide($return, $val): mixed { if ($return === false) return $val; if (is_string($return) and is_string($val)) return $return.$val; return oneof($val, $return); } /** * Function: call * Calls a trigger action. * * Parameters: * $name - The name of the trigger, or an array of triggers to call. * * Returns: * A concatenated string if all calls return a string, or; * @false@ if none of the triggers exist, or; * the most substantial returned value decided by oneof(). * * Notes: * Any additional arguments are passed on to the trigger responders. */ public function call($name): mixed { $return = false; if (is_array($name)) { foreach ($name as $call) { $args = func_get_args(); $args[0] = $call; $val = call_user_func_array( array($this, "call"), $args ); if ($val !== false) $return = $this->decide($return, $val); } return $return; } if (!$this->exists($name)) return $return; $arguments = func_get_args(); array_shift($arguments); $this->called[$name] = array(); if ( isset($this->priorities[$name]) and usort($this->priorities[$name], array($this, "cmp")) ) foreach ($this->priorities[$name] as $action) { $function = $action["function"]; if (is_array($function)) { $object = $function[0]; if (is_object($object) and !empty($object->cancelled)) continue; } $val = call_user_func_array($function, $arguments); $return = $this->decide($return, $val); $this->called[$name][] = $function; } foreach (Modules::$instances as $module) if ( is_callable(array($module, $name)) and !in_array(array($module, $name), $this->called[$name]) ) { if (!empty($module->cancelled)) continue; $val = call_user_func_array( array($module, $name), $arguments ); $return = $this->decide($return, $val); } return $return; } /** * Function: filter * Modify a variable by filtering it through a stack of trigger actions. * * Parameters: * &$target - The variable to filter. * $name - The name of the trigger. * * Returns: * $target, filtered through any/all actions for the trigger $name. * * Notes: * Any additional arguments are passed on to the trigger responders. */ public function filter(&$target, $name): mixed { if (is_array($name)) { foreach ($name as $filter) { $args = func_get_args(); $args[0] =& $target; $args[1] = $filter; $target = call_user_func_array( array($this, "filter"), $args ); } return $target; } if (!$this->exists($name)) return $target; $arguments = func_get_args(); array_shift($arguments); array_shift($arguments); $this->called[$name] = array(); if (isset($this->priorities[$name]) and usort($this->priorities[$name], array($this, "cmp")) ) foreach ($this->priorities[$name] as $action) { $function = $action["function"]; if (is_array($function)) { $object = $function[0]; if (is_object($object) and !empty($object->cancelled)) continue; } $val = call_user_func_array( $function, array_merge(array(&$target), $arguments) ); $this->called[$name][] = $function; $target = fallback($val, $target); } foreach (Modules::$instances as $module) if ( is_callable(array($module, $name)) and !in_array(array($module, $name), $this->called[$name]) ) { if (!empty($module->cancelled)) continue; $val = call_user_func_array( array($module, $name), array_merge(array(&$target), $arguments) ); $target = fallback($val, $target); } return $target; } /** * Function: exists * Checks if there are any actions for a given $trigger. * * Parameters: * $trigger - The trigger name. * * Returns: * @true@ or @false@ */ public function exists($name): bool { if (isset($this->exists[$name])) return $this->exists[$name]; foreach (Modules::$instances as $module) { if (is_callable(array($module, $name))) return $this->exists[$name] = true; } if (isset($this->priorities[$name])) return $this->exists[$name] = true; return $this->exists[$name] = false; } /** * Function: current * Returns a singleton reference to the current class. */ public static function & current(): self { static $instance = null; $instance = (empty($instance)) ? new self() : $instance ; return $instance; } }