<?php
namespace Fresh;
/**
* Handler is the source for extensability. You can set a handler either on the component & it will propagate, or set it directly on a view.
*
* @export(Class.Handler)
*/
class Handler {
protected $children = [];
protected $handlers = [];
public function __construct(){
}
public function addChild(object $childObj){
$this->children[] = $childObj;
foreach ($this->handlers as $domain => $handlers){
foreach ($handlers as $name=>$callbackList){
if (isset($callbackList['set'])){
$childObj->handler->setHandler($domain,$name,$callbackList['set']);
} else {
foreach ($callbackList as $index => $callback){
$childObj->handler->addHandler($domain,$name,$callback);
}
}
}
}
}
public function setHandler($domain,$name,$callback){
if (isset($this->handlers[$domain][$name]['set'])){
throw new \Exception("Cannot override a previous set handler for '{$domain}::{$name}'.");
}
$this->handlers[$domain][$name]['set'] = $callback;
foreach ($this->children as $child){
$handler = $child->handler;
$handler->setHandler($domain,$name,$callback);
}
}
public function addHandler($domain,$name,$data){
$existing = $this->handlers[$domain][$name] ?? null;
if ($existing!==null&&isset($existing['set'])){
$exDomain = var_export($domain,true);
$exName = var_export($name,true);
$class = get_class();
throw new \Exception("Cannot override handler previously set by calling {$class}::setHandler({$exDomain},{$exName},\$data) \n");
}
$this->handlers[$domain][$name][] = $data;
foreach ($this->children as $child){
$handler = $child->handler;
$handler->addHandler($domain,$name,$data);
}
}
/**
* Doing $handlerObject->compile will get an array of handlers in the 'compmile' domain, via the `__get` magic method.
* Then: `return (object)$arrayOfHandlers`... SO you have, simply, a cast object.
*
* TODO Create a HandlerDomain object that has magic methods to make calling more dev-friendly
* For each handler, if the handler was set with setHandler()... you can `$handler->compile->$HandlerName()`... and get a return value
* If the handler was put with addHandler()... Then $handler->compile->$HandlerName returns an array of handlers, which can each then be called.
*
*
* @export(Internals.Handler)
*/
public function __get($domain){
$handlers = $this->handlers[$domain] ?? null;
if ($handlers===null){
return null;
// print_r($this->handlers);
// throw new \Exception("No handlers exist for domain '{$domain}'.");
}
$ret = [];
foreach ($handlers as $name=>$list){
if (isset($list['set'])){
$ret[$name] = $list['set'];
} else {
$ret[$name] = $list;
}
}
return (object)$ret;
}
public function callMethod($domain,$method,$args){
$handler = $this->runtime->$method ?? null;
// echo "\n".$method;
if ($handler===null
||is_array($handler)&&count($handler)==0
// ||is_callable($handler)
// &&is_array($handler)
// &&!method_exists($handler[0],$handler[1])
){
// var_dump($this->handlers);
throw new \BadMethodCallException("Method '{$method}' does not exist ");
}
if (!is_callable($handler)&&is_array($handler)){
$ret = [];
foreach ($handler as $h){
$ret[] = $h(...$args);
}
return $ret;
} else {
return $handler(...$args);
}
}
}