Skip to content

Instantly share code, notes, and snippets.

@oranj
Last active December 9, 2015 23:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oranj/4343263 to your computer and use it in GitHub Desktop.
Save oranj/4343263 to your computer and use it in GitHub Desktop.
<?php
class Accessible {
const inst_prefix = 'inst_';
const stat_prefix = 'stat_';
const trans_prefix = 'trans_';
private $data = array();
private $inst_hooks = array(
'before' => array(),
'after' => array()
);
private static $static_hooks = array(
'before' => array(),
'after' => array()
);
public function __construct($id) {
$this->id = $id;
}
private function on_hook($function, $callback, $when) {
if (!! @$this) {
$this->inst_hooks[$when][$function] []= $callback;
} else {
self::$static_hooks[$when][get_called_class()][$function] []= $callback;
}
}
private function exe_hook($function, $arguments, $when) {
if (!! @$this) {
if (isset($this->inst_hooks[$when][$function])) {
foreach ($this->inst_hooks[$when][$function] as $callback) {
call_user_func_array($callback, $arguments);
}
}
} else {
if (isset(self::$static_hooks[$when][get_called_class()][$function])) {
foreach (self::$static_hooks[$when][get_called_class()][$function] as $callback) {
call_user_func_array($callback, $arguments);
}
}
}
}
public function get_inst_function($function, &$is_trans = false) {
$called_class = get_called_class();
if (method_exists($this, ($func = static::inst_prefix.$function))) {
return array($this, $func);
}
if (method_exists($called_class, ($func = static::trans_prefix.$function))) {
$is_trans = true;
return array($called_class, $func);
}
return null;
}
public static function get_stat_function($function, &$is_trans = false) {
$called_class = get_called_class();
if (method_exists($called_class, ($func = static::stat_prefix.$function))) {
return array($called_class, $func);
}
if (method_exists($called_class, ($func = static::trans_prefix.$function))) {
$is_trans = true;
return array($called_class, $func);
}
return null;
}
public function __call($name, $arguments = array()) {
if (preg_match('/^on_(?P<when>before|after)_(?P<func>.*)$/', $name, $matches) && ($callback = reset($arguments)) && is_callable($callback)) {
static::on_hook($matches['func'], $callback, $matches['when']);
return;
}
$function = $this->get_inst_function($name, $is_trans);
if ($function) {
if ($is_trans) { array_unshift($arguments, $this->id); }
$this->exe_hook($name, $arguments, 'before');
$out = call_user_func_array($function, $arguments);
$this->exe_hook($name, $arguments, 'after');
return $out;
}
trigger_error(sprintf("Function %s::%s is not defined", get_called_class(), $name));
}
public static function __callStatic($name, $arguments) {
if (preg_match('/^on_(?P<when>before|after)_(?P<func>.*)$/', $name, $matches) && ($callback = reset($arguments)) && is_callable($callback)) {
static::on_hook($matches['func'], $callback, $matches['when']);
return;
}
$function = static::get_stat_function($name, $is_trans);
if ($function) {
static::exe_hook($name, $arguments, 'before');
$out = call_user_func_array($function, $arguments);
static::exe_hook($name, $arguments, 'after');
return $out;
}
trigger_error(sprintf("Static function %s::%s is not defined", get_called_class(), $name));
}
public function __set($name, $value) {
$function = $this->get_inst_function($name);
if ($function) {
trigger_error(sprintf("Cannot set value of function %s::%s", get_called_class(), $name));
}
$this->data[$name] = $value;
}
public function __get($name) {
$function = $this->get_inst_function($name, $is_trans);
if ($function) {
$arguments = array();
if ($is_trans) { array_unshift($arguments, $this->id); }
$this->exe_hook($name, $arguments, 'before');
$out = call_user_func_array($function, $arguments);
$this->exe_hook($name, $arguments, 'after');
return $out;
}
if (isset($this->data[$name])) {
return $this->data[$name];
}
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment