added support for block renaming when importing traits
authorFabien Potencier <fabien.potencier@gmail.com>
Thu, 28 Apr 2011 21:57:39 +0000 (23:57 +0200)
committerFabien Potencier <fabien.potencier@gmail.com>
Thu, 28 Apr 2011 22:07:00 +0000 (00:07 +0200)
    {% use 'TwigBundle:Form:div_layout.html.twig' with text_widget as foo_text_widget %}

lib/Twig/Node/Module.php
lib/Twig/Parser.php
lib/Twig/TokenParser/Use.php

index 6f80e10..7776869 100644 (file)
@@ -73,25 +73,7 @@ class Twig_Node_Module extends Twig_Node
             ->indent();
         ;
 
-        if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
-            $compiler
-                ->write("\$this->parent = \$this->env->loadTemplate(")
-                ->subcompile($this->getNode('parent'))
-                ->raw(");\n")
-            ;
-        } else {
-            $compiler
-                ->write("\$this->parent = ")
-                ->subcompile($this->getNode('parent'))
-                ->raw(";\n")
-                ->write("if (!\$this->parent")
-                ->raw(" instanceof Twig_Template) {\n")
-                ->indent()
-                ->write("\$this->parent = \$this->env->loadTemplate(\$this->parent);\n")
-                ->outdent()
-                ->write("}\n")
-            ;
-        }
+        $this->compileLoadTemplate($compiler, $this->getNode('parent'), '$this->parent');
 
         $compiler
             ->outdent()
@@ -149,19 +131,31 @@ class Twig_Node_Module extends Twig_Node
 
         if (count($this->getNode('traits'))) {
             // traits
-            foreach ($this->getNode('traits') as $i => $node) {
+            foreach ($this->getNode('traits') as $i => $trait) {
+                $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i));
+
                 $compiler
-                    ->write(sprintf('$_trait_%s = $this->env->loadTemplate(', $i))
-                    ->subcompile($node)
-                    ->raw(");\n")
                     ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
                     ->indent()
                     ->write("throw new Twig_Error_Runtime('Template \"'.")
-                    ->subcompile($node)
+                    ->subcompile($trait->getNode('template'))
                     ->raw(".'\" cannot be used as a trait.');\n")
                     ->outdent()
-                    ->write("}\n\n");
+                    ->write("}\n")
+                    ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
                 ;
+
+                foreach ($trait->getNode('targets') as $key => $value) {
+                    $compiler
+                        ->write(sprintf("\$_trait_%s_blocks[", $i))
+                        ->subcompile($value)
+                        ->raw(sprintf("] = \$_trait_%s_blocks[", $i))
+                        ->string($key)
+                        ->raw(sprintf("]; unset(\$_trait_%s_blocks[", $i))
+                        ->string($key)
+                        ->raw("]);\n\n")
+                    ;
+                }
             }
 
             $compiler
@@ -171,7 +165,7 @@ class Twig_Node_Module extends Twig_Node
 
             for ($i = count($this->getNode('traits')) - 1; $i >= 0; --$i) {
                 $compiler
-                    ->write(sprintf("\$_trait_%s->getBlocks(),\n", $i))
+                    ->write(sprintf("\$_trait_%s_blocks,\n", $i))
                 ;
             }
 
@@ -289,4 +283,27 @@ class Twig_Node_Module extends Twig_Node
             ->write("}\n")
         ;
     }
+
+    public function compileLoadTemplate(Twig_Compiler $compiler, $node, $var)
+    {
+        if ($node instanceof Twig_Node_Expression_Constant) {
+            $compiler
+                ->write(sprintf("%s = \$this->env->loadTemplate(", $var))
+                ->subcompile($node)
+                ->raw(");\n")
+            ;
+        } else {
+            $compiler
+                ->write(sprintf("%s = ", $var))
+                ->subcompile($node)
+                ->raw(";\n")
+                ->write(sprintf("if (!%s", $var))
+                ->raw(" instanceof Twig_Template) {\n")
+                ->indent()
+                ->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var))
+                ->outdent()
+                ->write("}\n")
+            ;
+        }
+    }
 }
index 3f97184..be39535 100644 (file)
@@ -223,9 +223,9 @@ class Twig_Parser implements Twig_ParserInterface
         $this->macros[$name] = $node;
     }
 
-    public function addTrait($name)
+    public function addTrait($trait)
     {
-        $this->traits[] = $name;
+        $this->traits[] = $trait;
     }
 
     public function addImportedFunction($alias, $name, Twig_Node_Expression $node)
index a368611..5b8997a 100644 (file)
@@ -19,9 +19,36 @@ class Twig_TokenParser_Use extends Twig_TokenParser
      */
     public function parse(Twig_Token $token)
     {
-        $this->parser->addTrait($this->parser->getExpressionParser()->parseExpression());
+        $template = $this->parser->getExpressionParser()->parseExpression();
+        $stream = $this->parser->getStream();
 
-        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
+        $targets = array();
+        if ($stream->test('with')) {
+            $stream->next();
+
+            do {
+                $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
+
+                $alias = $name;
+                if ($stream->test('as')) {
+                    $stream->next();
+
+                    $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
+                }
+
+                $targets[$name] = new Twig_Node_Expression_Constant($alias, -1);
+
+                if (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
+                    break;
+                }
+
+                $stream->next();
+            } while (true);
+        }
+
+        $stream->expect(Twig_Token::BLOCK_END_TYPE);
+
+        $this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets))));
 
         return null;
     }