freenet-router |
Subversion Repositories: |
Compare with Previous - Blame - Download
<?php
namespace Phem\Core;
/**
* Description of ObjectMixin
*
* @author Vejvis
*/
final class ObjectMixin
{
/** @var array */
private static $methods;
/**
* Returns property value.
* @param object
* @param string property name
* @return mixed property value
* @throws MemberAccessException if the property is not defined.
*/
public static function & get($_this, $name)
{
$class = get_class($_this);
if ($name === '')
{
throw new MemberAccessException("Cannot read a class '$class' property without name.");
}
if (!isset(self::$methods[$class]))
{
// get_class_methods returns ONLY PUBLIC methods of objects
// but returns static methods too (nothing doing...)
// and is much faster than reflection
// (works good since 5.0.4)
self::$methods[$class] = array_flip(get_class_methods($class));
}
// public method as closure getter
if (isset(self::$methods[$class][$name]))
{
$val = function() use ($_this, $name)
{
return call_user_func_array(array($_this, $name), func_get_args());
};
return $val;
}
// property getter support
$name[0] = $name[0] & "\xDF"; // case-sensitive checking, capitalize first character
$m = 'get' . $name;
if (isset(self::$methods[$class][$m]))
{
// ampersands:
// - uses &__get() because declaration should be forward compatible
// - doesn't call &$_this->$m because user could bypass property setter by: $x = & $obj->property; $x = 'new value';
$val = $_this->$m();
return $val;
}
$m = 'is' . $name;
if (isset(self::$methods[$class][$m]))
{
$val = $_this->$m();
return $val;
}
$type = isset(self::$methods[$class]['set' . $name]) ? 'a write-only' : 'an undeclared';
$name = func_get_arg(1);
throw new MemberAccessException("Cannot read $type property $class::\$$name.");
}
/**
* Sets value of a property.
* @param object
* @param string property name
* @param mixed property value
* @return void
* @throws MemberAccessException if the property is not defined or is read-only
*/
public static function set($_this, $name, $value)
{
$class = get_class($_this);
if ($name === '')
{
throw new MemberAccessException("Cannot write to a class '$class' property without name.");
}
if (!isset(self::$methods[$class]))
{
self::$methods[$class] = array_flip(get_class_methods($class));
}
// property setter support
$name[0] = $name[0] & "\xDF"; // case-sensitive checking, capitalize first character
$m = 'set' . $name;
if (isset(self::$methods[$class][$m]))
{
$_this->$m($value);
return;
}
$type = isset(self::$methods[$class]['get' . $name]) || isset(self::$methods[$class]['is' . $name]) ? 'a read-only' : 'an undeclared';
$name = func_get_arg(1);
throw new MemberAccessException("Cannot write to $type property $class::\$$name.");
}
}