rendered paste body/**------------------------------------------------------------------------------------------------
@modifies Obj
@brief Creates a singleton out of any class.
-------------------------------------------------------------------------------------------------*/
uses "reflection", "array";
/*------------------------------------------------------------------------------------------------*/
class modifies Obj {
directive Hookable() {
eval("
class modifies ${Class.name(self)} {
static array hookers;
static function addHooker(void hooker, array events) {
string name = Class.name(hooker);
events.each() using (event) {
if (!.hookers.keyExists(event)) {
.hookers['' + event] = [];
}
.hookers['' + event]['' + name] = hooker;
};
}
static function removeHooker(void hooker) {
array events;
.hookers.eachWithIndex() using (event, index) {
events.push(.hookers.getName(index));
};
.removeHooker(hooker, events);
}
static function removeHooker(void hooker, array events) {
string name = Class.name(hooker);
events.each() using (event) {
if (.hookers.keyExists(event)) {
.hookers['' + event] = .hookers['' + event].subtract([name => '']);
}
};
}
function callHooker(string event, array with) {
array args = arguments();
if (!Hookable.hookers.keyExists(event)) { return with; }
Hookable.hookers['' + event].each() using (hooker) {
object hookerClass = new Class(hooker);
object hookerFunction = hookerClass.getFunction(event);
monitor {
with = hookerFunction.exec(with);
} handle (error) {
object request = new Request();
request.print('' + error.num);
}
};
return with;
}
}");
}
}
/*------------------------------------------------------------------------------------------------*/
class Hookable {
[Hookable];
function doSomething() {
object request = new Request();
string output = "I don't know what to do!";
array with;
// We need a hooker!
with = .callHooker("doSomething", [output]);
request.print(with[0] + "<br />");
}
}
/*------------------------------------------------------------------------------------------------*/
class Hooker {
static constructor() {
}
//static function doSomething(array with) {
static function doSomething() {
with[0] = "I know what to do!";
// Don't want to handle this anymore!
Hookable.removeHooker(self);
return with;
}
}
/*------------------------------------------------------------------------------------------------*/
object hooker = new Hookable();
Hookable.addHooker(Hooker, ["doSomething"]);
hooker.doSomething();
hooker.doSomething();
/*------------------------------------------------------------------------------------------------*/