From: Fabien Potencier Date: Mon, 7 Jun 2010 08:41:15 +0000 (+0200) Subject: made Resource::getAttribute() more generic (WIP) X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=f2bb0aa9117ef43fb39a0932705fa08b6e0f182a;p=web%2Fkonrad%2Ftwig.git made Resource::getAttribute() more generic (WIP) --- diff --git a/lib/Twig/ExpressionParser.php b/lib/Twig/ExpressionParser.php index 53c49fd..a86d7c1 100644 --- a/lib/Twig/ExpressionParser.php +++ b/lib/Twig/ExpressionParser.php @@ -370,21 +370,28 @@ class Twig_ExpressionParser $token = $this->parser->getStream()->next(); $lineno = $token->getLine(); $arguments = new Twig_Node(); + $type = Twig_Node_Expression_GetAttr::TYPE_ANY; if ($token->getValue() == '.') { $token = $this->parser->getStream()->next(); if ($token->getType() == Twig_Token::NAME_TYPE || $token->getType() == Twig_Token::NUMBER_TYPE) { $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); + if ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '(')) { + $type = Twig_Node_Expression_GetAttr::TYPE_METHOD; + } + $arguments = $this->parseArguments(); } else { throw new Twig_SyntaxError('Expected name or number', $lineno); } } else { + $type = Twig_Node_Expression_GetAttr::TYPE_ARRAY; + $arg = $this->parseExpression(); $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ']'); } - return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $lineno, $token->getValue()); + return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $lineno, $type); } public function parseFilterExpression($node) diff --git a/lib/Twig/Node/Expression/GetAttr.php b/lib/Twig/Node/Expression/GetAttr.php index 3803849..583c890 100644 --- a/lib/Twig/Node/Expression/GetAttr.php +++ b/lib/Twig/Node/Expression/GetAttr.php @@ -11,9 +11,13 @@ */ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression { - public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_NodeInterface $arguments, $lineno, $token_value = null) + const TYPE_ANY = 'any'; + const TYPE_ARRAY = 'array'; + const TYPE_METHOD = 'method'; + + public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_NodeInterface $arguments, $lineno, $type = self::TYPE_ANY) { - parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('token_value' => $token_value), $lineno); + parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type), $lineno); } public function compile($compiler) @@ -33,13 +37,9 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression ; } - $compiler->raw(')'); - - // Don't look for functions if they're using foo[bar] - if ('[' == $this['token_value']) { - $compiler->raw(', true'); - } - - $compiler->raw(')'); + $compiler + ->raw('), ') + ->repr($this['type']) + ->raw(')'); } } diff --git a/lib/Twig/Resource.php b/lib/Twig/Resource.php index c30a115..0386a0b 100644 --- a/lib/Twig/Resource.php +++ b/lib/Twig/Resource.php @@ -37,30 +37,43 @@ abstract class Twig_Resource throw new InvalidArgumentException(sprintf('Item "%s" from context does not exist.', $item)); } - protected function getAttribute($object, $item, array $arguments = array(), $arrayOnly = false) + protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_Node_Expression_GetAttr::TYPE_ANY) { - $item = (string) $item; + // array + if (Twig_Node_Expression_GetAttr::TYPE_METHOD !== $type) { + if ((is_array($object) || is_object($object) && $object instanceof ArrayAccess) && isset($object[$item])) { + return $object[$item]; + } + + if (Twig_Node_Expression_GetAttr::TYPE_ARRAY === $type) { + if (!$this->env->isStrictVariables()) { + return null; + } - if ((is_array($object) || is_object($object) && $object instanceof ArrayAccess) && isset($object[$item])) { - return $object[$item]; + throw new InvalidArgumentException(sprintf('Key "%s" for array "%s" does not exist.', $item, $object)); + } } - if ($arrayOnly || !is_object($object)) { + if (!is_object($object)) { if (!$this->env->isStrictVariables()) { return null; } - throw new InvalidArgumentException(sprintf('Key "%s" for array "%s" does not exist.', $item, $object)); + throw new InvalidArgumentException(sprintf('Item "%s" for "%s" does not exist.', $item, $object)); } - if (isset($object->$item)) { - if ($this->env->hasExtension('sandbox')) { - $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item); - } + // object property + if (Twig_Node_Expression_GetAttr::TYPE_METHOD !== $type) { + if (isset($object->$item)) { + if ($this->env->hasExtension('sandbox')) { + $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item); + } - return $object->$item; + return $object->$item; + } } + // object method $class = get_class($object); if (!isset($this->cache[$class])) { diff --git a/test/Twig/Tests/Node/Expression/GetAttrTest.php b/test/Twig/Tests/Node/Expression/GetAttrTest.php index b7f4393..4694ae2 100644 --- a/test/Twig/Tests/Node/Expression/GetAttrTest.php +++ b/test/Twig/Tests/Node/Expression/GetAttrTest.php @@ -24,12 +24,12 @@ class Twig_Tests_Node_Expression_GetAttrTest extends Twig_Tests_Node_TestCase new Twig_Node_Expression_Name('foo', 0), new Twig_Node_Expression_Constant('bar', 0), )); - $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, '['); + $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, Twig_Node_Expression_GetAttr::TYPE_ARRAY); $this->assertEquals($expr, $node->node); $this->assertEquals($attr, $node->attribute); $this->assertEquals($args, $node->arguments); - $this->assertEquals('[', $node['token_value']); + $this->assertEquals(Twig_Node_Expression_GetAttr::TYPE_ARRAY, $node['type']); } /** @@ -49,17 +49,18 @@ class Twig_Tests_Node_Expression_GetAttrTest extends Twig_Tests_Node_TestCase $attr = new Twig_Node_Expression_Constant('bar', 0); $args = new Twig_Node(); $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0); - $tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array())'); + $tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array(), "any")'); + + $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, Twig_Node_Expression_GetAttr::TYPE_ARRAY); + $tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array(), "array")'); - $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, '['); - $tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array(), true)'); $args = new Twig_Node(array( new Twig_Node_Expression_Name('foo', 0), new Twig_Node_Expression_Constant('bar', 0), )); - $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0); - $tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array($this->getContext($context, \'foo\'), "bar", ))'); + $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, 0, Twig_Node_Expression_GetAttr::TYPE_METHOD); + $tests[] = array($node, '$this->getAttribute($this->getContext($context, \'foo\'), "bar", array($this->getContext($context, \'foo\'), "bar", ), "method")'); return $tests; }