Skip to content

Instantly share code, notes, and snippets.

@ringmaster
Created March 25, 2014 13:30
Show Gist options
  • Save ringmaster/9761789 to your computer and use it in GitHub Desktop.
Save ringmaster/9761789 to your computer and use it in GitHub Desktop.
<?php
class OC_Hook extends ArrayObject {
static protected $registered = array();
protected $abort = false;
protected $callbacks = array();
protected $signal = '';
public static function connect($classname, $signalname, $callback) {
if(!isset(self::$registered[$signalname])) {
self::$registered[$signalname] = array();
}
self::$registered[$signalname][$classname] = $callback;
}
public static function compact($parameters) {
$c = __CLASS__;
return new $c($parameters);
}
public static function emit($signalname, \OC_Hook $parameters = null) {
if(empty($parameters)) {
$parameters = \OC_Hook::compact(array());
}
if(isset(self::$registered[$signalname])) {
$parameters->doEmit($signalname, self::$registered[$signalname]);
}
}
public function doEmit($signalname, $callbacks) {
$this->signal = $signalname;
$this->callbacks = $callbacks;
if(count($this->callbacks)) {
$this->next();
}
}
public function next() {
$key = key($this->callbacks);
$next = array_shift($this->callbacks);
try {
call_user_func($next, $this);
}
catch (\Exception $e) {
// Log exception
echo "Caught exception while running {$this->signal} for {$key}.\n";
}
if(!$this->abort && count($this->callbacks)) {
$this->next();
}
}
public function abort() {
$this->abort = true;
}
public function has($key) {
$key = is_array($key) ? $key : array($key);
return count(array_intersect(array_keys($this->callbacks), $key)) > 0;
}
public function getSignal() {
return $this->signal;
}
public function until($key, $callback) {
while($this->has($key) && !$this->abort) {
$this->next();
}
if(!$this->abort) {
call_user_func($callback, $this);
}
}
}
OC_Hook::connect('foo', 'sig1', function(OC_Hook $params) {
// wait until 'qux' fires, then abort
$params->until('qux', function(OC_Hook $params){
$params['new'] = 'This is newer.';
$params->abort();
});
});
OC_Hook::connect('bar', 'sig1', function(OC_Hook $params) {
$params['new'] = 'This is new.';
$params->next();
});
OC_Hook::connect('baz', 'sig1', function(OC_Hook $params) {
$params['change'] = 'This is changed.';
});
OC_Hook::connect('qux', 'sig1', function(OC_Hook $params) {
throw new \Exception('test hook exceptions');
});
OC_Hook::connect('quux', 'sig1', function(OC_Hook $params) {
$params['new'] = 'This is too new.';
// This one won't execute because abort() was called from foo
});
OC_Hook::emit('sig1', $result = OC_Hook::compact(array('change'=>'old value')));
extract($result->getArrayCopy());
var_dump($change, $new);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment