From 10cab461299144f089d0e4aa81f4d1142f96105d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 1 Nov 2010 04:24:32 +0100 Subject: [PATCH] made the include tag more flexible --- CHANGELOG | 2 ++ doc/02-Twig-for-Template-Designers.markdown | 17 ++++++++++++++--- lib/Twig/Node/Include.php | 22 +++++++++++++++++----- lib/Twig/TokenParser/Include.php | 9 ++++++++- test/Twig/Tests/Fixtures/tags/include/only.test | 16 ++++++++++++++++ test/Twig/Tests/Node/IncludeTest.php | 15 ++++++++++----- 6 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 test/Twig/Tests/Fixtures/tags/include/only.test diff --git a/CHANGELOG b/CHANGELOG index a349573..7fd14fa 100644 --- 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) diff --git a/doc/02-Twig-for-Template-Designers.markdown b/doc/02-Twig-for-Template-Designers.markdown index 52d296b..296ddf1 100644 --- a/doc/02-Twig-for-Template-Designers.markdown +++ b/doc/02-Twig-for-Template-Designers.markdown @@ -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. - diff --git a/lib/Twig/Node/Include.php b/lib/Twig/Node/Include.php index 15c1f1d..6b25c56 100644 --- a/lib/Twig/Node/Include.php +++ b/lib/Twig/Node/Include.php @@ -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"); diff --git a/lib/Twig/TokenParser/Include.php b/lib/Twig/TokenParser/Include.php index cfdaab7..cd44803 100644 --- a/lib/Twig/TokenParser/Include.php +++ b/lib/Twig/TokenParser/Include.php @@ -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 index 0000000..474adcc --- /dev/null +++ b/test/Twig/Tests/Fixtures/tags/include/only.test @@ -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, diff --git a/test/Twig/Tests/Node/IncludeTest.php b/test/Twig/Tests/Node/IncludeTest.php index e6ccb55..aa876ee 100644 --- a/test/Twig/Tests/Node/IncludeTest.php +++ b/test/Twig/Tests/Node/IncludeTest.php @@ -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, << 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; -- 1.7.2.5