Created
February 4, 2012 15:55
-
-
Save swvitaliy/1738673 to your computer and use it in GitHub Desktop.
Mixins in php5.3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* mixin.php | |
* Mixin emulation in php 5.3 | |
* | |
* Author: swvitaliy | |
*/ | |
class MixinContainer extends stdClass { | |
private $_mixin_protectes = array(); | |
protected $_mixin_objs = array(); | |
protected function _mixin_call_($name, $args, &$found = null) { | |
$found = $this->$name instanceof ReflectionMethod; | |
if ($found) { | |
$mixinObj = $this->_mixin_objs[$this->$name->class]; | |
$mixinObj->_mixin_before_call_($name, $this); | |
return $this->$name->invokeArgs($mixinObj, $args); | |
} | |
} | |
public function __call($name, $args) { | |
return $this->_mixin_call_($name, $args); | |
} | |
protected function _mixin_init_($mixinName) { | |
$mixinClass = new ReflectionClass($mixinName); | |
$thisClass = new ReflectionClass($this); | |
foreach ($mixinClass->getDefaultProperties() as $propName=>$propValue) { | |
if ($thisClass->hasProperty($propName)) continue; | |
$property = $mixinClass->getProperty($propName); | |
if (!$property->isStatic() && strpos($propName, '_mixin_')!==0) { | |
$this->$propName = $propValue; | |
if ($property->isProtected()) | |
$this->_mixin_protectes [$propName] = $propValue; | |
} | |
} | |
foreach ($mixinClass->getMethods() as $mixinMethod) { | |
$methodName = $mixinMethod->getName(); | |
if ($thisClass->hasMethod($methodName)) continue; | |
if (!$mixinMethod->isStatic() && $mixinMethod->isPublic() && strpos($methodName, '_mixin_')!==0) | |
$this->$methodName = $mixinMethod; | |
} | |
$this->_mixin_objs [$mixinName] = new $mixinName; | |
} | |
protected function _mixin_super_($mixinName, $mixinMethod) { | |
$args = array_slice(func_get_args(), 2); | |
$mixinObj = $this->_mixin_objs[$mixinName]; | |
$mixinObj->_mixin_before_call_($mixinMethod, $this); | |
$reflectMethod = new ReflectionMethod($mixinName, $mixinMethod); | |
return $reflectMethod->invokeArgs($mixinObj, $args); | |
} | |
} | |
class Mixin extends stdClass { | |
protected static $_mixin_meta_ = array ( | |
// relations | |
// 'method' => array ('property1', 'property2', /* etc */), | |
); | |
public function _mixin_before_call_($methodName, MixinContainer $container) { | |
if (!isset(static::$_mixin_meta_[$methodName])) | |
return; | |
$properties = static::$_mixin_meta_[$methodName]; | |
foreach ($properties as $property) | |
$this->$property = $container->$property; | |
} | |
} | |
/* | |
class T0 extends Mixin { | |
const to_c = 't0_c'; | |
public static $t0_pus = 't0_pus'; | |
protected static $t0_pros = 't0_pros'; | |
private static $t0_pris = 't0_pris'; | |
public static function t0_pusf() { return 't0_pusf'; } | |
protected static function t0_prosf() { return 't0_prosf'; } | |
private static function t0_prisf() { return 't0_prisf'; } | |
public $t0_pu = 't0_pu'; | |
protected $t0_pro = 't0_pro'; | |
private $t0_pri = 't0_pri'; | |
public function t0_puf() { return 't0_puf'; } | |
protected function t0_prof() { return 't0_prof'; } | |
private function t0_prif() { return 't0_prif'; } | |
public function t0_prif_test() { return $this->t0_prif(); } | |
public function t0_prof_test() { return $this->t0_prof(); } | |
} | |
class A extends MixinContainer { | |
public function __construct() { | |
$this->_mixin_init_('T0'); | |
} | |
} | |
// access error | |
// $t0 = new T0; | |
// $t0->t0_pro = 'sd'; | |
$a = new A(); | |
echo $a->t0_pu . "\n"; | |
// access error? | |
echo $a->to_pro = "blablabla\n"; // now it public property :( | |
//echo $a->t0_pro . "\n"; | |
//echo $a->t0_pri . "\n"; | |
// errors | |
//echo A::t0_pus . "\n"; | |
//echo A::t0_pros . "\n"; | |
//echo A::t0_pris . "\n"; | |
echo $a->t0_puf() . "\n"; | |
echo $a->t0_prof_test() . "\n"; | |
echo $a->t0_prif_test() . "\n"; | |
class T1 extends Mixin { | |
protected static $_mixin_meta_ = array ( | |
'message' => array('t1_hello', 't1_who'), | |
); | |
public $t1_hello = 'Hello'; | |
public $t1_who = 'World!'; | |
public function message () { return $this->t1_hello . ' ' . $this->t1_who; } | |
} | |
class B extends MixinContainer { | |
public function __construct() { | |
$this->_mixin_init_('T1'); | |
} | |
} | |
$b = new B; | |
echo $b->message() . "\n"; | |
$b->t1_who = 'Jonny!'; | |
echo $b->message() . "\n"; | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment