<?php
namespace Lia\Compo;
/**
* Events are the primary way that different packages and different parts of a package communicate with one another.
* Any component (using the base package) may declare `onNamespace_EventName($event,$arg1,$arg2,....)` to automatically have the event registered when the package is added.
* Namespaces aren't entirely required, but it's better that way.
*
* Each Event callable will receive an `$event` object. This object is always the same \Lia\Event component object. This needs to be improved.
*
*
* @export(old.Event.Class)
*/
class oldEvent { //extends \Lia\Compo {
public $name = null;
/**
* - Figure out how events are going to work
* - Implement an events directory, possibly
* - Rename register & send to schedule & emit
* - Should events offer return values? No, I don't think so
*
* @export(TODO.Events)
*/
protected $events = [];
/**
* - register($eventName, $object, $method=null): Register the event to be executed
* - if `$method` is `null`, `$object` MUST have a method 'on$eventName'
* - if `$method` is a string, the a callable will be stored as [$object, $method]
* - Uses the Event component of the base package
* - The first paramater of your callback must take an `$event` object (which is poorly implemented)
* - It may accept any paramaters after that, as specified by the registered event
* - This might be renamed soon
* - send($eventName,$arg1, $arg2, $arg3, ....): Execute the given event, passing the list of args along.
* - has($eventName): check if event has been registered.
* @export(old.Event.register)
*/
public function register($EventName,$compo,$methodName=null){
$this->events[$EventName] = $this->events[$EventName] ?? [];
$this->events[$EventName][] = $methodName==null ? [$compo,'on'.$EventName] : [$compo,$methodName];
}
public function has($EventName){
$events = $this->events[$EventName] ?? [];
return (count($events)>0);
}
public function send($EventName,...$args){
if (!$this->has($EventName)){
if (in_array($EventName,$this->package->lia->get('Events.debug_ignore',[]))){
return;
}
trigger_error("Event '{$EventName}' has not been registered by any component.");
if ($this->package->lia->get('Events.debug')){
echo "\n\n";
$events = [];
foreach ($this->events as $key=>$eventList){
foreach ($eventList as $event){
$events[$key][] = get_class($event[0]).'->'.$event[1];
}
}
print_r($events);
throw new \Exception("\n\nRegistered events are shown above.");
}
return;
}
$events = $this->events;
$event = $this->_buildEvent($EventName, $args);
$allReturns = [];
$matchedEvents = $events[$EventName];
if (count($matchedEvents)>1
&&$EventName!='Events_Sort'){
/**
* When an event has multiple methods registered to it, the Events_Sort event is called, to allow you to filter which methods to execute.
* If you implement the Events_Sort event, you must return an array of all the events that should be executed.
* Your method should be like:
* ```php
* onEvents_Sort($event,$EventName,$argsArray,$arrayOfEvents){
* //unset one of the events because... the dog barked
* return $arrayOfEvents;
* }
* ```
*
* If there are multiple methods registered to Events_Sort... that's bad. It'll break stuff
*
* @export(old.Event.Events_Sort)
*/
$sortedEvents = $this->Events_Sort($EventName,$args,$matchedEvents);
}
$eventList = $sortedEvents ?? $matchedEvents;
foreach ($eventList as $index=>$callable){
$ret =
$allReturns[] = call_user_func($callable,$event,...$args);
}
$returnVal = $this->getReturnValue($allReturns,$EventName);
return $returnVal;
}
public function __call($EventName, $args){
if (ucfirst($EventName)!==$EventName){
throw new \Exception("Event '{$EventName}' cannot be sent, because ALL events MUST start with a capital letter.\n");
}
return $this->send($EventName,...$args);
}
protected function _buildEvent($EventName, $args){
return $this;
return [
'cats'
];
}
/**
* Return values from an event call depend upon how many events are registered and what they return.
* - 0 registered events: Return null
* - 1 registered event: Return the exact value returned by that event
* - 2+ registered events: Any return value === null will be discarded
* - all other return values will be added to an array
* - That null-filtered array will then be re-checked for 0 or 1 values
* - If the null-filtered array has more than 1 value, an array of return values will be returned, in no intentional order.
*
* You may further refine this by registering to the event "Resolve{$EventName}".
* The resolve event will also follow the return value rules as listed here, so you could potentionally have an event like 'ResolveResolveResolveTooManyRegistered'.
* Like, please don't do that? Lol. But you caaannn... I think.
*
* @export(old.Events.ReturnValue)
*/
protected function getReturnValue($allReturns,$EventName){
if (count($allReturns)==0)return null;
else if (count($allReturns)==1) return $allReturns[0];
else if (count($allReturns)>1){
$nullFilteredCopy = [];
foreach ($allReturns as $index => $return){
if ($return!==null)
$nullFilteredCopy[] = $return;
}
if ($nullFilteredCopy!==$allReturns)return $this->getReturnValue($nullFilteredCopy,$EventName);
if ($this->has($event='Resolve'.$EventName)){
$rets = $this->$event($allReturns);
return $rets;
}
throw new \Exception("Event '{$EventName}' cannot be returned becasue there were multiple return values.");
// return $allReturns;
}
}
}