fixed the attribute function when passing arguments (closes #608)
authorFabien Potencier <fabien.potencier@gmail.com>
Mon, 23 Jan 2012 07:47:30 +0000 (08:47 +0100)
committerFabien Potencier <fabien.potencier@gmail.com>
Mon, 23 Jan 2012 07:51:52 +0000 (08:51 +0100)
CHANGELOG
lib/Twig/ExpressionParser.php
lib/Twig/Node/Expression/GetAttr.php
test/Twig/Tests/Fixtures/functions/attribute.test
test/Twig/Tests/Fixtures/macros/simple.test
test/Twig/Tests/Node/Expression/GetAttrTest.php

index 75cd2e6..3c3e07d 100644 (file)
--- 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
index ddbdc8f..ca2c5f0 100644 (file)
@@ -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);
index e6f5ba2..6498444 100644 (file)
@@ -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'));
index 635ae29..ba7d5e8 100644 (file)
@@ -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
index f5bc1f6..6a366cd 100644 (file)
@@ -4,14 +4,19 @@ macro
 {% import _self as test %}
 {% from _self import test %}
 
-{% macro test() -%}
-    foo<br />
+{% macro test(a, b) -%}
+    {{ a|default('a') }}<br />
+    {{- b|default('b') }}<br />
 {%- endmacro %}
 
 {{ test.test() }}
 {{ test() }}
+{{ test.test(1, "c") }}
+{{ test(1, "c") }}
 --DATA--
 return array();
 --EXPECT--
-foo<br />
-foo<br />
+a<br />b<br />
+a<br />b<br />
+1<br />c<br />
+1<br />c<br />
index 3893748..6df143d 100644 (file)
@@ -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;
     }