public static function call($_this, $name, $args)
{
$class = get_class($_this);
$isProp = self::hasProperty($class, $name);
if ($name === '') {
throw new MemberAccessException("Call to class '{$class}' method without name.");
} elseif ($isProp === 'event') {
// calling event handlers
if (is_array($_this->{$name}) || $_this->{$name} instanceof \Traversable) {
foreach ($_this->{$name} as $handler) {
Callback::invokeArgs($handler, $args);
}
} elseif ($_this->{$name} !== NULL) {
throw new Nette\UnexpectedValueException("Property {$class}::\${$name} must be array or NULL, " . gettype($_this->{$name}) . ' given.');
}
} elseif ($isProp && $_this->{$name} instanceof \Closure) {
// closure in property
return call_user_func_array($_this->{$name}, $args);
} elseif (($methods =& self::getMethods($class)) && isset($methods[$name]) && is_array($methods[$name])) {
// magic @methods
list($op, $rp, $type) = $methods[$name];
if (count($args) !== ($op === 'get' ? 0 : 1)) {
throw new Nette\InvalidArgumentException("{$class}::{$name}() expects " . ($op === 'get' ? 'no' : '1') . ' argument, ' . count($args) . ' given.');
} elseif ($type && $args && !self::checkType($args[0], $type)) {
throw new Nette\InvalidArgumentException("Argument passed to {$class}::{$name}() must be {$type}, " . gettype($args[0]) . ' given.');
}
if ($op === 'get') {
return $rp->getValue($_this);
} elseif ($op === 'set') {
$rp->setValue($_this, $args[0]);
} elseif ($op === 'add') {
$val = $rp->getValue($_this);
$val[] = $args[0];
$rp->setValue($_this, $val);
}
return $_this;
} elseif ($cb = self::getExtensionMethod($class, $name)) {
// extension methods
return Callback::invoke($cb, $_this, ...$args);
} else {
self::strictCall($class, $name, array_keys(self::getExtensionMethods($class)));
}
}