added the special _context variable to reference the current context
authorFabien Potencier <fabien.potencier@gmail.com>
Tue, 29 Jun 2010 06:33:25 +0000 (08:33 +0200)
committerFabien Potencier <fabien.potencier@gmail.com>
Tue, 29 Jun 2010 06:33:25 +0000 (08:33 +0200)
CHANGELOG
doc/02-Twig-for-Template-Designers.markdown
lib/Twig/Node/Expression/Name.php
lib/Twig/Node/Import.php
lib/Twig/Template.php
test/Twig/Tests/Fixtures/tags/macro/basic.test
test/Twig/Tests/Fixtures/tags/macro/self_import.test
test/Twig/Tests/Node/Expression/NameTest.php
test/Twig/Tests/integrationTest.php

index 981832c..b91e3d7 100644 (file)
--- 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)
index abc8b16..552b85a 100644 (file)
@@ -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:
     <p>{{ forms.input('password', none, 'password') }}</p>
 
 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]
-    <p>{{ self.input('username') }}</p>
+    <p>{{ _self.input('username') }}</p>
 
-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) %}
         <div class="field">
-            {{ self.input(name, value, type, size) }}
+            {{ _self.input(name, value, type, size) }}
         </div>
     {% endmacro %}
 
@@ -776,7 +785,7 @@ Importing these macros in a template is as easy as using the `import` tag:
     <p>{{ forms.textarea('comment') }}</p>
 
 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:
       <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>
     {% endmacro %}
 
-    <p>{{ self.textarea('comment') }}</p>
+    <p>{{ _self.textarea('comment') }}</p>
 
-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:
       <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea>
     {% endmacro %}
 
-    {% import self as forms %}
+    {% import _self as forms %}
 
     <p>{{ forms.textarea('comment') }}</p>
 
index a7001a3..daf6d80 100644 (file)
@@ -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 {
index 5d917da..0e94f3c 100644 (file)
@@ -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
index cafccc0..98af1f1 100644 (file)
@@ -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;
             }
 
index a1460ec..ef59a57 100644 (file)
@@ -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) %}
   <input type="{{ type|default("text") }}" name="{{ name }}" value="{{ value|e|default('') }}" size="{{ size|default(20) }}">
index ae55df8..17756cb 100644 (file)
@@ -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) }}
index 3010aea..b5345a7 100644 (file)
@@ -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'),
         );
     }
 }
index f7a8760..9958d51 100644 (file)
@@ -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.')');
         }
     }
 }