added a way to dynamically change the auto-escaping strategy according to the templat...
authorFabien Potencier <fabien.potencier@gmail.com>
Wed, 25 Apr 2012 04:25:28 +0000 (06:25 +0200)
committerFabien Potencier <fabien.potencier@gmail.com>
Wed, 25 Apr 2012 05:12:38 +0000 (07:12 +0200)
CHANGELOG
lib/Twig/Environment.php
lib/Twig/Extension/Escaper.php
lib/Twig/NodeVisitor/Escaper.php
test/Twig/Tests/EnvironmentTest.php [new file with mode: 0644]

index c76909a..a4be99f 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,6 @@
 * 1.8.0 (2012-XX-XX)
 
+ * added a way to dynamically change the auto-escaping strategy according to the template "filename"
  * changed the autoescape option to also accept a supported escaping strategy (for BC, true is equivalent to html)
  * added an embed tag
 
index bfd307b..8026e72 100644 (file)
@@ -73,6 +73,7 @@ class Twig_Environment
      *                  * false: disable auto-escaping
      *                  * true: equivalent to html
      *                  * html, js: set the autoescaping to one of the supported strategies
+     *                  * PHP callback: a PHP callback that returns an escaping strategy based on the template "filename"
      *
      *  * optimizations: A flag that indicates which optimizations to apply
      *                   (default to -1 which means that all optimizations are enabled;
index 686cc90..2eedef9 100644 (file)
@@ -54,8 +54,12 @@ class Twig_Extension_Escaper extends Twig_Extension
         );
     }
 
-    public function getDefaultStrategy()
+    public function getDefaultStrategy($filename)
     {
+        if (is_callable($this->defaultStrategy)) {
+            return call_user_func($this->defaultStrategy, $filename);
+        }
+
         return $this->defaultStrategy;
     }
 
index d57c307..f442ce7 100644 (file)
@@ -21,6 +21,7 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
     protected $blocks = array();
     protected $safeAnalysis;
     protected $traverser;
+    protected $defaultStrategy = false;
 
     public function __construct()
     {
@@ -37,7 +38,11 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
      */
     public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
     {
-        if ($node instanceof Twig_Node_AutoEscape) {
+        if ($node instanceof Twig_Node_Module) {
+            if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
+                $this->defaultStrategy = $defaultStrategy;
+            }
+        } elseif ($node instanceof Twig_Node_AutoEscape) {
             $this->statusStack[] = $node->getAttribute('value');
         } elseif ($node instanceof Twig_Node_Block) {
             $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
@@ -56,7 +61,9 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
      */
     public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
     {
-        if ($node instanceof Twig_Node_Expression_Filter) {
+        if ($node instanceof Twig_Node_Module) {
+            $this->defaultStrategy = false;
+        } elseif ($node instanceof Twig_Node_Expression_Filter) {
             return $this->preEscapeFilterNode($node, $env);
         } elseif ($node instanceof Twig_Node_Print) {
             return $this->escapePrintNode($node, $env, $this->needEscaping($env));
@@ -135,8 +142,8 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
             return $this->statusStack[count($this->statusStack) - 1];
         }
 
-        if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy()) {
-            return $defaultStrategy;
+        if ($this->defaultStrategy) {
+            return $this->defaultStrategy;
         }
 
         return false;
diff --git a/test/Twig/Tests/EnvironmentTest.php b/test/Twig/Tests/EnvironmentTest.php
new file mode 100644 (file)
index 0000000..bb31690
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+class Twig_Tests_EnvironmentTest extends PHPUnit_Framework_TestCase
+{
+    public function testAutoescapeOption()
+    {
+        $loader = new Twig_Loader_Array(array(
+            'html' => '{{ foo }} {{ foo }}',
+            'js'   => '{{ bar }} {{ bar }}',
+        ));
+
+        $twig = new Twig_Environment($loader, array(
+            'debug'      => true,
+            'cache'      => false,
+            'autoescape' => array($this, 'escapingStrategyCallback'),
+        ));
+
+        $this->assertEquals('foo&lt;br/ &gt; foo&lt;br/ &gt;', $twig->render('html', array('foo' => 'foo<br/ >')));
+        $this->assertEquals('foo\x3cbr\x2f \x3e foo\x3cbr\x2f \x3e', $twig->render('js', array('bar' => 'foo<br/ >')));
+    }
+
+    public function escapingStrategyCallback($filename)
+    {
+        return $filename;
+    }
+}