mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-15 20:06:31 +00:00
added support for __call() in expression resolution (closes #2)
The new algorithm for object method resolution is now the following: * get all methods declared for `$object` using ReflectionObject::getMethods() * check if `$item` is in the list of method names * check if `get$item` is in the list of method names * check if `__call` is defined and pass `$item` as the method name
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
* 0.9.6-DEV
|
||||
|
||||
* added support for __call() in expression resolution
|
||||
* fixed node visiting for macros (macros are now visited by visitors as any other node)
|
||||
* fixed nested block definitions with a parent call (rarely useful but nonetheless supported now)
|
||||
* added the cycle filter
|
||||
* fixed the Lexer when mbstring.func_overload is used with an mbstring.internal_encoding different from ASCII
|
||||
|
||||
+30
-9
@@ -11,10 +11,12 @@
|
||||
abstract class Twig_Resource
|
||||
{
|
||||
protected $env;
|
||||
protected $cache;
|
||||
|
||||
public function __construct(Twig_Environment $env)
|
||||
{
|
||||
$this->env = $env;
|
||||
$this->cache = array();
|
||||
}
|
||||
|
||||
public function getEnvironment()
|
||||
@@ -36,12 +38,12 @@ abstract class Twig_Resource
|
||||
return $object[$item];
|
||||
}
|
||||
|
||||
if ($arrayOnly)
|
||||
if ($arrayOnly || !is_object($object))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_object($object) && isset($object->$item))
|
||||
if (isset($object->$item))
|
||||
{
|
||||
if ($this->env->hasExtension('sandbox'))
|
||||
{
|
||||
@@ -51,13 +53,32 @@ abstract class Twig_Resource
|
||||
return $object->$item;
|
||||
}
|
||||
|
||||
if (
|
||||
!is_object($object) ||
|
||||
(
|
||||
!method_exists($object, $method = $item) &&
|
||||
!method_exists($object, $method = 'get'.$item)
|
||||
)
|
||||
)
|
||||
$class = get_class($object);
|
||||
|
||||
if (!isset($this->cache[$class]))
|
||||
{
|
||||
$r = new ReflectionClass($class);
|
||||
$this->cache[$class] = array();
|
||||
foreach ($r->getMethods(ReflectionMethod::IS_STATIC | ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_FINAL) as $method)
|
||||
{
|
||||
$this->cache[$class][strtolower($method->getName())] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$item = strtolower($item);
|
||||
if (isset($this->cache[$class][$item]))
|
||||
{
|
||||
$method = $item;
|
||||
}
|
||||
elseif (isset($this->cache[$class]['get'.$item]))
|
||||
{
|
||||
$method = 'get'.$item;
|
||||
}
|
||||
elseif (isset($this->cache[$class]['__call']))
|
||||
{
|
||||
$method = $item;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
--TEST--
|
||||
Twig supports __call() for attributes
|
||||
--TEMPLATE--
|
||||
{{ foo.foo }}
|
||||
{{ foo.bar }}
|
||||
--DATA--
|
||||
class TestClassForMagicCallAttributes
|
||||
{
|
||||
public function getBar()
|
||||
{
|
||||
return 'bar_from_getbar';
|
||||
}
|
||||
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
if ('foo' === $method)
|
||||
{
|
||||
return 'foo_from_call';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return array('foo' => new TestClassForMagicCallAttributes())
|
||||
--EXPECT--
|
||||
foo_from_call
|
||||
bar_from_getbar
|
||||
Reference in New Issue
Block a user