made the include tag more flexible
authorFabien Potencier <fabien.potencier@gmail.com>
Mon, 1 Nov 2010 03:24:32 +0000 (04:24 +0100)
committerFabien Potencier <fabien.potencier@gmail.com>
Mon, 1 Nov 2010 03:24:32 +0000 (04:24 +0100)
CHANGELOG
doc/02-Twig-for-Template-Designers.markdown
lib/Twig/Node/Include.php
lib/Twig/TokenParser/Include.php
test/Twig/Tests/Fixtures/tags/include/only.test [new file with mode: 0644]
test/Twig/Tests/Node/IncludeTest.php

index a349573..7fd14fa 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,8 @@ Backward incompatibilities:
         sub-nodes are now accessed via getNode() (instead of property access)
         attributes via getAttribute() (instead of array access)
  * the urlencode filter had been renamed to url_encode
+ * the include tag now merges the passed variables with the current context by default
+   (the old behavior is still possible by adding the "only" keyword)
 
  * the implementation of template inheritance has been rewritten
    (blocks can now be called individually and still work with inheritance)
index 52d296b..296ddf1 100644 (file)
@@ -734,7 +734,7 @@ Template inheritance above.
 ### Include
 
 The `include` statement is useful to include a template and return the
-rendered contents of that file into the current namespace:
+rendered content of that file into the current namespace:
 
     [twig]
     {% include 'header.html' %}
@@ -743,17 +743,28 @@ rendered contents of that file into the current namespace:
 
 Included templates have access to the variables of the active context.
 
-You can also restrict the variables passed to the template by explicitly pass
-them as an array:
+You can add additional variables by passing them after the `with` keyword:
 
     [twig]
+    {# the foo template will have access to the variables from the current context and the foo one #}
     {% include 'foo' with ['foo': 'bar'] %}
 
     {% set vars = ['foo': 'bar'] %}
     {% include 'foo' with vars %}
 
+You can disable access to the context by appending the `only` keyword:
+
+    [twig]
+    {# only the foo variable will be accessible #}
+    {% include 'foo' with ['foo': 'bar'] only %}
+
+    [twig]
+    {# no variable will be accessible #}
+    {% include 'foo' only %}
+
 >**NOTE**
 >The `with` keyword is supported as of Twig 0.9.5.
+>The `only` keyword is supported as of Twig 0.9.9.
 
 -
 
index 15c1f1d..6b25c56 100644 (file)
@@ -19,9 +19,9 @@
  */
 class Twig_Node_Include extends Twig_Node
 {
-    public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $lineno, $tag = null)
+    public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $lineno, $tag = null)
     {
-        parent::__construct(array('expr' => $expr, 'variables' => $variables), array(), $lineno, $tag);
+        parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (Boolean) $only), $lineno, $tag);
     }
 
     /**
@@ -54,10 +54,22 @@ class Twig_Node_Include extends Twig_Node
             ;
         }
 
-        if (null === $this->getNode('variables')) {
-            $compiler->raw('$context');
+        if (false === $this->getAttribute('only')) {
+            if (null === $this->getNode('variables')) {
+                $compiler->raw('$context');
+            } else {
+                $compiler
+                    ->raw('array_merge($context, ')
+                    ->subcompile($this->getNode('variables'))
+                    ->raw(')')
+                ;
+            }
         } else {
-            $compiler->subcompile($this->getNode('variables'));
+            if (null === $this->getNode('variables')) {
+                $compiler->raw('array()');
+            } else {
+                $compiler->subcompile($this->getNode('variables'));
+            }
         }
 
         $compiler->raw(");\n");
index cfdaab7..cd44803 100644 (file)
@@ -29,9 +29,16 @@ class Twig_TokenParser_Include extends Twig_TokenParser
             $variables = $this->parser->getExpressionParser()->parseExpression();
         }
 
+        $only = false;
+        if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'only')) {
+            $this->parser->getStream()->next();
+
+            $only = true;
+        }
+
         $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
 
-        return new Twig_Node_Include($expr, $variables, $token->getLine(), $this->getTag());
+        return new Twig_Node_Include($expr, $variables, $only, $token->getLine(), $this->getTag());
     }
 
     /**
diff --git a/test/Twig/Tests/Fixtures/tags/include/only.test b/test/Twig/Tests/Fixtures/tags/include/only.test
new file mode 100644 (file)
index 0000000..474adcc
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+"include" tag accept variables and only
+--TEMPLATE--
+{% include "foo.twig" %}
+{% include "foo.twig" only %}
+{% include "foo.twig" with ['foo1': 'bar'] %}
+{% include "foo.twig" with ['foo1': 'bar'] only %}
+--TEMPLATE(foo.twig)--
+{% for k, v in _context %}{{ k }},{% endfor %}
+--DATA--
+return array('foo' => 'bar')
+--EXPECT--
+foo,_parent,
+_parent,
+foo,foo1,_parent,
+foo1,_parent,
index e6ccb55..aa876ee 100644 (file)
@@ -19,14 +19,16 @@ class Twig_Tests_Node_IncludeTest extends Twig_Tests_Node_TestCase
     public function testConstructor()
     {
         $expr = new Twig_Node_Expression_Constant('foo.twig', 0);
-        $node = new Twig_Node_Include($expr, null, 0);
+        $node = new Twig_Node_Include($expr, null, false, 0);
 
         $this->assertEquals(null, $node->getNode('variables'));
         $this->assertEquals($expr, $node->getNode('expr'));
+        $this->assertFalse($node->getAttribute('only'));
 
         $vars = new Twig_Node_Expression_Array(array('foo' => new Twig_Node_Expression_Constant(true, 0)), 0);
-        $node = new Twig_Node_Include($expr, $vars, 0);
+        $node = new Twig_Node_Include($expr, $vars, true, 0);
         $this->assertEquals($vars, $node->getNode('variables'));
+        $this->assertTrue($node->getAttribute('only'));
     }
 
     /**
@@ -43,7 +45,7 @@ class Twig_Tests_Node_IncludeTest extends Twig_Tests_Node_TestCase
         $tests = array();
 
         $expr = new Twig_Node_Expression_Constant('foo.twig', 0);
-        $node = new Twig_Node_Include($expr, null, 0);
+        $node = new Twig_Node_Include($expr, null, false, 0);
         $tests[] = array($node, '$this->env->loadTemplate("foo.twig")->display($context);');
 
         $expr = new Twig_Node_Expression_Conditional(
@@ -52,7 +54,7 @@ class Twig_Tests_Node_IncludeTest extends Twig_Tests_Node_TestCase
                         new Twig_Node_Expression_Constant('foo', 0),
                         0
                     );
-        $node = new Twig_Node_Include($expr, null, 0);
+        $node = new Twig_Node_Include($expr, null, false, 0);
         $tests[] = array($node, <<<EOF
 \$template = (true) ? ("foo") : ("foo");
 if (!\$template instanceof Twig_Template) {
@@ -64,7 +66,10 @@ EOF
 
         $expr = new Twig_Node_Expression_Constant('foo.twig', 0);
         $vars = new Twig_Node_Expression_Array(array('foo' => new Twig_Node_Expression_Constant(true, 0)), 0);
-        $node = new Twig_Node_Include($expr, $vars, 0);
+        $node = new Twig_Node_Include($expr, $vars, false, 0);
+        $tests[] = array($node, '$this->env->loadTemplate("foo.twig")->display(array_merge($context, array("foo" => true)));');
+
+        $node = new Twig_Node_Include($expr, $vars, true, 0);
         $tests[] = array($node, '$this->env->loadTemplate("foo.twig")->display(array("foo" => true));');
 
         return $tests;