made the set tag more powerful
authorfabien <fabien@93ef8e89-cb99-4229-a87c-7fa0fa45744b>
Tue, 27 Oct 2009 16:31:56 +0000 (16:31 +0000)
committerfabien <fabien@93ef8e89-cb99-4229-a87c-7fa0fa45744b>
Tue, 27 Oct 2009 16:31:56 +0000 (16:31 +0000)
git-svn-id: http://svn.twig-project.org/trunk@103 93ef8e89-cb99-4229-a87c-7fa0fa45744b

doc/02-Twig-for-Template-Designers.markdown
doc/04-Extending-Twig.markdown
lib/Twig/Node/Set.php
lib/Twig/TokenParser/Set.php
test/fixtures/tags/set/basic.test [new file with mode: 0644]
test/unit/integrationTest.php

index 876d8eb..d9de144 100644 (file)
@@ -507,7 +507,7 @@ the `set` tag and can have multiple targets:
     [twig]
     {% set foo as 'foo' %}
 
-    {% set key, value as call_something() %}
+    {% set foo, bar as 'foo', 'bar' %}
 
 ### Extends
 
index e8041ad..fa6dc5f 100644 (file)
@@ -152,12 +152,18 @@ Let's create a simple `set` tag that allows the definition of simple variables
 from within a template. The tag can be used like follows:
 
     [twig]
-    {% set name "value" %}
+    {% set name as "value" %}
 
     {{ name }}
 
     {# should output value #}
 
+>**NOTE**
+>The `set` tag is part of the Core extension and as such is always available.
+>The built-in version is slightly more powerful and supports multiple
+>assignments by defaults (cf. template designers chapter for more
+>information).
+
 First, we need to create a `Twig_TokenParser` class which will be able to
 parse this new language construct:
 
@@ -189,6 +195,7 @@ Now, let's see the actual code of the token parser class:
       {
         $lineno = $token->getLine();
         $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue();
+        $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, 'as');
         $value = $this->parser->getExpressionParser()->parseExpression();
 
         $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
@@ -212,7 +219,8 @@ stream (`$this->parser->getStream()`):
    returns it.
 
  * `expect()`: Expects a token and returns it (like `test()`) or throw a
-   syntax error if not found.
+   syntax error if not found (the second argument is the expected value of the
+   token).
 
  * `look()`: Looks a the next token. This is how you can have a look at the
    next token without consume it.
index 6e3503b..0d367c6 100644 (file)
@@ -3,16 +3,16 @@
 class Twig_Node_Set extends Twig_Node
 {
   protected $names;
-  protected $value;
+  protected $values;
   protected $isMultitarget;
 
-  public function __construct($isMultitarget, $names, Twig_Node_Expression $value, $lineno, $tag = null)
+  public function __construct($isMultitarget, $names, $values, $lineno, $tag = null)
   {
     parent::__construct($lineno, $tag);
 
     $this->isMultitarget = $isMultitarget;
     $this->names = $names;
-    $this->value = $value;
+    $this->values = $values;
   }
 
   public function compile($compiler)
@@ -46,10 +46,27 @@ class Twig_Node_Set extends Twig_Node
       ;
     }
 
-    $compiler
-      ->raw(' = ')
-      ->subcompile($this->value)
-      ->raw(";\n")
-    ;
+    $compiler->raw(' = ');
+
+    if ($this->isMultitarget)
+    {
+      $compiler->write('array(');
+      foreach ($this->values as $idx => $value)
+      {
+        if ($idx)
+        {
+          $compiler->raw(', ');
+        }
+
+        $compiler->subcompile($value);
+      }
+      $compiler->raw(')');
+    }
+    else
+    {
+      $compiler->subcompile($this->values);
+    }
+
+    $compiler->raw(";\n");
   }
 }
index e31d1e6..8ab170e 100644 (file)
@@ -7,11 +7,16 @@ class Twig_TokenParser_Set extends Twig_TokenParser
     $lineno = $token->getLine();
     list($isMultitarget, $names) = $this->parser->getExpressionParser()->parseAssignmentExpression();
     $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, 'as');
-    $value = $this->parser->getExpressionParser()->parseExpression();
+    list(, $values) = $this->parser->getExpressionParser()->parseAssignmentExpression();
 
     $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
 
-    return new Twig_Node_Set($isMultitarget, $names, $value, $lineno, $this->getTag());
+    if (count($names) !== count($values))
+    {
+      throw new Twig_SyntaxError("When using set, you must have the same number of variables and assignements.", $lineno);
+    }
+
+    return new Twig_Node_Set($isMultitarget, $names, $values, $lineno, $this->getTag());
   }
 
   public function getTag()
diff --git a/test/fixtures/tags/set/basic.test b/test/fixtures/tags/set/basic.test
new file mode 100644 (file)
index 0000000..9c6fbd1
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+"set" tag
+--TEMPLATE--
+{% set foo as 'foo' %}
+
+{{ foo }}
+
+{% set foo, bar as 'foo', 'bar' %}
+
+{{ foo }}{{ bar }}
+--DATA--
+return array()
+--EXPECT--
+foo
+
+
+foobar
index 48f3b0f..e34bf4d 100644 (file)
@@ -35,7 +35,7 @@ class Foo
   }
 }
 
-$t = new LimeTest(48);
+$t = new LimeTest(49);
 $fixturesDir = realpath(dirname(__FILE__).'/../fixtures/');
 
 foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file)