From 883a93bb4da3f8fede107a53032ef2b9d6ee22eb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 23 Jan 2012 08:47:30 +0100 Subject: [PATCH] fixed the attribute function when passing arguments (closes #608) --- CHANGELOG | 1 + lib/Twig/ExpressionParser.php | 17 +++++++++++------ lib/Twig/Node/Expression/GetAttr.php | 13 ++----------- test/Twig/Tests/Fixtures/functions/attribute.test | 2 ++ test/Twig/Tests/Fixtures/macros/simple.test | 13 +++++++++---- test/Twig/Tests/Node/Expression/GetAttrTest.php | 19 ++++++++----------- 6 files changed, 33 insertions(+), 32 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 75cd2e6..3c3e07d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ * 1.6.0-DEV + * fixed the attribute function when passing arguments * added slice notation support for the [] operator (syntactic sugar for the slice operator) * added a slice filter * added string support for the reverse filter diff --git a/lib/Twig/ExpressionParser.php b/lib/Twig/ExpressionParser.php index ddbdc8f..ca2c5f0 100644 --- a/lib/Twig/ExpressionParser.php +++ b/lib/Twig/ExpressionParser.php @@ -303,13 +303,18 @@ class Twig_ExpressionParser return new Twig_Node_Expression_BlockReference($args->getNode(0), false, $line); case 'attribute': if (count($args) < 2) { - throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attribute)', $line); + throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line); } return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_TemplateInterface::ANY_CALL, $line); default: if (null !== $alias = $this->parser->getImportedFunction($name)) { - return new Twig_Node_Expression_GetAttr($alias['node'], new Twig_Node_Expression_Constant($alias['name'], $line), $args, Twig_TemplateInterface::METHOD_CALL, $line); + $arguments = new Twig_Node_Expression_Array(array(), $line); + foreach ($args as $n) { + $arguments->addElement($n); + } + + return new Twig_Node_Expression_GetAttr($alias['node'], new Twig_Node_Expression_Constant($alias['name'], $line), $arguments, Twig_TemplateInterface::METHOD_CALL, $line); } $class = $this->getFunctionNodeClass($name); @@ -323,7 +328,7 @@ class Twig_ExpressionParser $stream = $this->parser->getStream(); $token = $stream->next(); $lineno = $token->getLine(); - $arguments = new Twig_Node(); + $arguments = new Twig_Node_Expression_Array(array(), $lineno); $type = Twig_TemplateInterface::ANY_CALL; if ($token->getValue() == '.') { $token = $stream->next(); @@ -338,9 +343,9 @@ class Twig_ExpressionParser if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { $type = Twig_TemplateInterface::METHOD_CALL; - $arguments = $this->parseArguments(); - } else { - $arguments = new Twig_Node(); + foreach ($this->parseArguments() as $n) { + $arguments->addElement($n); + } } } else { throw new Twig_Error_Syntax('Expected name or number', $lineno); diff --git a/lib/Twig/Node/Expression/GetAttr.php b/lib/Twig/Node/Expression/GetAttr.php index e6f5ba2..6498444 100644 --- a/lib/Twig/Node/Expression/GetAttr.php +++ b/lib/Twig/Node/Expression/GetAttr.php @@ -11,7 +11,7 @@ */ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression { - public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_NodeInterface $arguments, $type, $lineno) + public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno) { parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false), $lineno); } @@ -33,16 +33,7 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression $compiler->raw(', ')->subcompile($this->getNode('attribute')); if (count($this->getNode('arguments')) || Twig_TemplateInterface::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { - $compiler->raw(', array('); - - foreach ($this->getNode('arguments') as $node) { - $compiler - ->subcompile($node) - ->raw(', ') - ; - } - - $compiler->raw(')'); + $compiler->raw(', ')->subcompile($this->getNode('arguments')); if (Twig_TemplateInterface::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { $compiler->raw(', ')->repr($this->getAttribute('type')); diff --git a/test/Twig/Tests/Fixtures/functions/attribute.test b/test/Twig/Tests/Fixtures/functions/attribute.test index 635ae29..ba7d5e8 100644 --- a/test/Twig/Tests/Fixtures/functions/attribute.test +++ b/test/Twig/Tests/Fixtures/functions/attribute.test @@ -3,8 +3,10 @@ --TEMPLATE-- {{ attribute(obj, method) }} {{ attribute(array, item) }} +{{ attribute(obj, "bar", ["a", "b"]) }} --DATA-- return array('obj' => new Foo(), 'method' => 'foo', 'array' => array('foo' => 'bar'), 'item' => 'foo') --EXPECT-- foo bar +bar_a-b diff --git a/test/Twig/Tests/Fixtures/macros/simple.test b/test/Twig/Tests/Fixtures/macros/simple.test index f5bc1f6..6a366cd 100644 --- a/test/Twig/Tests/Fixtures/macros/simple.test +++ b/test/Twig/Tests/Fixtures/macros/simple.test @@ -4,14 +4,19 @@ macro {% import _self as test %} {% from _self import test %} -{% macro test() -%} - foo
+{% macro test(a, b) -%} + {{ a|default('a') }}
+ {{- b|default('b') }}
{%- endmacro %} {{ test.test() }} {{ test() }} +{{ test.test(1, "c") }} +{{ test(1, "c") }} --DATA-- return array(); --EXPECT-- -foo
-foo
+a
b
+a
b
+1
c
+1
c
diff --git a/test/Twig/Tests/Node/Expression/GetAttrTest.php b/test/Twig/Tests/Node/Expression/GetAttrTest.php index 3893748..6df143d 100644 --- a/test/Twig/Tests/Node/Expression/GetAttrTest.php +++ b/test/Twig/Tests/Node/Expression/GetAttrTest.php @@ -20,10 +20,9 @@ class Twig_Tests_Node_Expression_GetAttrTest extends Twig_Tests_Node_TestCase { $expr = new Twig_Node_Expression_Name('foo', 0); $attr = new Twig_Node_Expression_Constant('bar', 0); - $args = new Twig_Node(array( - new Twig_Node_Expression_Name('foo', 0), - new Twig_Node_Expression_Constant('bar', 0), - )); + $args = new Twig_Node_Expression_Array(array(), 0); + $args->addElement(new Twig_Node_Expression_Name('foo', 0)); + $args->addElement(new Twig_Node_Expression_Constant('bar', 0)); $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ARRAY_CALL, 0); $this->assertEquals($expr, $node->getNode('node')); @@ -47,20 +46,18 @@ class Twig_Tests_Node_Expression_GetAttrTest extends Twig_Tests_Node_TestCase $expr = new Twig_Node_Expression_Name('foo', 0); $attr = new Twig_Node_Expression_Constant('bar', 0); - $args = new Twig_Node(); + $args = new Twig_Node_Expression_Array(array(), 0); $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ANY_CALL, 0); $tests[] = array($node, sprintf('%s%s, "bar")', $this->getAttributeGetter(), $this->getVariableGetter('foo'))); $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::ARRAY_CALL, 0); $tests[] = array($node, sprintf('%s%s, "bar", array(), "array")', $this->getAttributeGetter(), $this->getVariableGetter('foo'))); - - $args = new Twig_Node(array( - new Twig_Node_Expression_Name('foo', 0), - new Twig_Node_Expression_Constant('bar', 0), - )); + $args = new Twig_Node_Expression_Array(array(), 0); + $args->addElement(new Twig_Node_Expression_Name('foo', 0)); + $args->addElement(new Twig_Node_Expression_Constant('bar', 0)); $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_TemplateInterface::METHOD_CALL, 0); - $tests[] = array($node, sprintf('%s%s, "bar", array(%s, "bar", ), "method")', $this->getAttributeGetter(), $this->getVariableGetter('foo'), $this->getVariableGetter('foo'))); + $tests[] = array($node, sprintf('%s%s, "bar", array(0 => %s, 1 => "bar"), "method")', $this->getAttributeGetter(), $this->getVariableGetter('foo'), $this->getVariableGetter('foo'))); return $tests; } -- 1.7.2.5