Skip to content

Instantly share code, notes, and snippets.

@jbrumwell
Forked from dhotson/oo.php
Created September 23, 2010 18:56
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jbrumwell/594135 to your computer and use it in GitHub Desktop.
Save jbrumwell/594135 to your computer and use it in GitHub Desktop.
<?php
// Define the 'class' class
$class = Obj()
->fn('new', function ($class) {
$newClass = Obj($class->methods)
->fn('new', function($class) {
$obj = Obj($class->imethods);
$args = func_get_args();
array_shift($args);
call_user_func_array(array($obj, 'init'), $args);
return $obj;
});
return $newClass;
})
->fn('def', function ($t, $name, $fn) {
$t->imethods[$name] = $fn;
return $t;
})
->fn('extend', function ($t) {
return clone $t;
});
// Define a new class
$animal = $class->new()
->def('init', function($t, $name) {
$t->name = $name;
})
->def('speak', function($t) {
echo "My name is $t->name\n";
});
// Extend a class
$dog = $animal->extend()
->def('speak', function($t) {
echo "My name is $t->name, I have just met you and I love you, SQUIRREL!\n";
})
->def('bark', function($t) {
echo "Woof!\n";
});
$jimmy = $animal->new('Jimmy');
$jimmy->speak();
$doug = $dog->new('Doug');
$doug->speak();
$doug->bark();
// ---- The guts...
class Obj
{
protected $inceptors = array();
protected $sequences = array();
public function __construct($methods=array())
{
$this->methods = $methods;
}
public function method($name)
{
if (!isset($this->methods[$name]))
throw new BadMethodCallException();
return $this->methods[$name];
}
public function fn($name, $fn)
{
$this->methods[$name] = $fn;
return $this;
}
public function intercept($name,$fn=null) {
if (is_callable($fn)) {
$this->intercept[$name][] = $fn;
} else {
$arguments = $fn;
foreach ($this->intercept[$name] as $interceptor) {
$arguments = call_user_func_array(
$this->method($name),
array_merge(array($this), $arguments)
);
if (false === $arguments) {
break;
}
}
}
return $arguments;
}
public function sequence($name,$fn=null) {
if (is_callable($fn)) {
$this->sequence[$name][] = $fn;
} else {
$return = $fn;
foreach ($this->sequence[$name] as $interceptor) {
$return = call_user_func_array(
$this->method($name),
array_merge(array($this), $return)
);
}
}
return $return;
}
public function __call($name, $args)
{
if (isset($this->inceptors[$name])) {
$args = $this->intercept($name,$args);
}
if (false !== $args) {
$return = call_user_func_array(
$this->method($name),
array_merge(array($this), $args)
);
if (isset($this->sequence[$name])) {
$return = $this->sequence($name,$args);
}
}
return $return;
}
}
// Allow chaining method calls off the constructor..
function Obj($methods=array())
{
return new Obj($methods);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment