From 80af31538a40aa9ecc18403986fc242a2c083cbe Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 29 Jun 2010 08:33:25 +0200 Subject: [PATCH] added the special _context variable to reference the current context --- CHANGELOG | 5 ++++ doc/02-Twig-for-Template-Designers.markdown | 25 +++++++++++++------ lib/Twig/Node/Expression/Name.php | 4 ++- lib/Twig/Node/Import.php | 2 +- lib/Twig/Template.php | 2 +- test/Twig/Tests/Fixtures/tags/macro/basic.test | 4 +- .../Tests/Fixtures/tags/macro/self_import.test | 2 +- test/Twig/Tests/Node/Expression/NameTest.php | 4 +++ test/Twig/Tests/integrationTest.php | 5 ++- 9 files changed, 37 insertions(+), 16 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 981832c..b91e3d7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,10 @@ * 0.9.9 +Backward incompatibilities: + * the self special variable has been renamed to _self + + * added the special _context variable to reference the current context + * renamed self to _self (to avoid conflict) * fixed Twig_Template::getAttribute() for protected properties * 0.9.8 (2010-06-28) diff --git a/doc/02-Twig-for-Template-Designers.markdown b/doc/02-Twig-for-Template-Designers.markdown index abc8b16..552b85a 100644 --- a/doc/02-Twig-for-Template-Designers.markdown +++ b/doc/02-Twig-for-Template-Designers.markdown @@ -104,6 +104,11 @@ If a variable or attribute does not exist you will get back a `null` value > [twig] > foo[bar] +Twig always references two special variables (mostly useful for macros): + + * `_self`: references the current template; + * `_context`: references the current context. + Filters ------- @@ -589,6 +594,10 @@ Macros differs from native PHP functions in a few ways: But as PHP functions, macros don't have access to the current template variables. +>**TIP** +>You can pass the whole context as an argument by using the special `_context` +>variable. + Macros can be defined in any template, and need to be "imported" before being used (see the Import section for more information): @@ -606,12 +615,12 @@ The macro can then be called at will:

{{ forms.input('password', none, 'password') }}

If the macros are defined and used in the same template, you can use the -special `self` variable, without importing them: +special `_self` variable, without importing them: [twig] -

{{ self.input('username') }}

+

{{ _self.input('username') }}

-When you want to use a macro in another one from the same file, use the `self` +When you want to use a macro in another one from the same file, use the `_self` variable: [twig] @@ -621,7 +630,7 @@ variable: {% macro wrapped_input(name, value, type, size) %}
- {{ self.input(name, value, type, size) }} + {{ _self.input(name, value, type, size) }}
{% endmacro %} @@ -776,7 +785,7 @@ Importing these macros in a template is as easy as using the `import` tag:

{{ forms.textarea('comment') }}

Importing is not needed if the macros and the template are defined in the file; -use the special `self` variable instead: +use the special `_self` variable instead: [twig] {# index.html template #} @@ -785,9 +794,9 @@ use the special `self` variable instead: {% endmacro %} -

{{ self.textarea('comment') }}

+

{{ _self.textarea('comment') }}

-But you can still create an alias by importing from the `self` variable: +But you can still create an alias by importing from the `_self` variable: [twig] {# index.html template #} @@ -796,7 +805,7 @@ But you can still create an alias by importing from the `self` variable: {% endmacro %} - {% import self as forms %} + {% import _self as forms %}

{{ forms.textarea('comment') }}

diff --git a/lib/Twig/Node/Expression/Name.php b/lib/Twig/Node/Expression/Name.php index a7001a3..daf6d80 100644 --- a/lib/Twig/Node/Expression/Name.php +++ b/lib/Twig/Node/Expression/Name.php @@ -18,8 +18,10 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression public function compile($compiler) { - if ('self' === $this['name']) { + if ('_self' === $this['name']) { $compiler->raw('$this'); + } elseif ('_context' === $this['name']) { + $compiler->raw('$context'); } elseif ($compiler->getEnvironment()->isStrictVariables()) { $compiler->raw(sprintf('$this->getContext($context, \'%s\')', $this['name'], $this['name'])); } else { diff --git a/lib/Twig/Node/Import.php b/lib/Twig/Node/Import.php index 5d917da..0e94f3c 100644 --- a/lib/Twig/Node/Import.php +++ b/lib/Twig/Node/Import.php @@ -37,7 +37,7 @@ class Twig_Node_Import extends Twig_Node ->raw(' = ') ; - if ($this->expr instanceof Twig_Node_Expression_Name && 'self' === $this->expr['name']) { + if ($this->expr instanceof Twig_Node_Expression_Name && '_self' === $this->expr['name']) { $compiler->raw("\$this"); } else { $compiler diff --git a/lib/Twig/Template.php b/lib/Twig/Template.php index cafccc0..98af1f1 100644 --- a/lib/Twig/Template.php +++ b/lib/Twig/Template.php @@ -108,7 +108,7 @@ abstract class Twig_Template implements Twig_TemplateInterface if (!isset($this->cache[$class])) { $r = new ReflectionClass($class); $this->cache[$class] = array(); - foreach ($r->getMethods(ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_FINAL) as $method) { + foreach ($r->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { $this->cache[$class]['methods'][strtolower($method->getName())] = true; } diff --git a/test/Twig/Tests/Fixtures/tags/macro/basic.test b/test/Twig/Tests/Fixtures/tags/macro/basic.test index a1460ec..ef59a57 100644 --- a/test/Twig/Tests/Fixtures/tags/macro/basic.test +++ b/test/Twig/Tests/Fixtures/tags/macro/basic.test @@ -1,8 +1,8 @@ --TEST-- "macro" tag --TEMPLATE-- -{{ self.input('username') }} -{{ self.input('password', null, 'password', 1) }} +{{ _self.input('username') }} +{{ _self.input('password', null, 'password', 1) }} {% macro input(name, value, type, size) %} diff --git a/test/Twig/Tests/Fixtures/tags/macro/self_import.test b/test/Twig/Tests/Fixtures/tags/macro/self_import.test index ae55df8..17756cb 100644 --- a/test/Twig/Tests/Fixtures/tags/macro/self_import.test +++ b/test/Twig/Tests/Fixtures/tags/macro/self_import.test @@ -1,7 +1,7 @@ --TEST-- "macro" tag --TEMPLATE-- -{% import self as forms %} +{% import _self as forms %} {{ forms.input('username') }} {{ forms.input('password', null, 'password', 1) }} diff --git a/test/Twig/Tests/Node/Expression/NameTest.php b/test/Twig/Tests/Node/Expression/NameTest.php index 3010aea..b5345a7 100644 --- a/test/Twig/Tests/Node/Expression/NameTest.php +++ b/test/Twig/Tests/Node/Expression/NameTest.php @@ -35,12 +35,16 @@ class Twig_Tests_Node_Expression_NameTest extends Twig_Tests_Node_TestCase public function getTests() { $node = new Twig_Node_Expression_Name('foo', 0); + $self = new Twig_Node_Expression_Name('_self', 0); + $context = new Twig_Node_Expression_Name('_context', 0); $env = new Twig_Environment(null, array('strict_variables' => true)); return array( array($node, '$this->getContext($context, \'foo\')', $env), array($node, '(isset($context[\'foo\']) ? $context[\'foo\'] : null)'), + array($self, '$this'), + array($context, '$context'), ); } } diff --git a/test/Twig/Tests/integrationTest.php b/test/Twig/Tests/integrationTest.php index f7a8760..9958d51 100644 --- a/test/Twig/Tests/integrationTest.php +++ b/test/Twig/Tests/integrationTest.php @@ -65,15 +65,16 @@ class Twig_Tests_IntegrationTest extends PHPUnit_Framework_TestCase $output = trim($template->render(eval($match[1].';')), "\n "); $expected = trim($match[2], "\n "); - $this->assertEquals($expected, $output, $message.' (in '.$file.')'); - if ($output != $expected) { + if ($expected != $output) { echo 'Compiled template that failed:'; foreach (array_keys($templates) as $name) { + echo "Template: $name\n"; $source = $loader->getSource($name); echo $twig->compile($twig->parse($twig->tokenize($source, $name))); } } + $this->assertEquals($expected, $output, $message.' (in '.$file.')'); } } } -- 1.7.2.5