From 1f00c33acde77c1c3eb5c2c13c292f5e5afcffda Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 25 Apr 2012 06:25:28 +0200 Subject: [PATCH] added a way to dynamically change the auto-escaping strategy according to the template filename --- CHANGELOG | 1 + lib/Twig/Environment.php | 1 + lib/Twig/Extension/Escaper.php | 6 +++++- lib/Twig/NodeVisitor/Escaper.php | 15 +++++++++++---- test/Twig/Tests/EnvironmentTest.php | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 test/Twig/Tests/EnvironmentTest.php diff --git a/CHANGELOG b/CHANGELOG index c76909a..a4be99f 100644 --- 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 diff --git a/lib/Twig/Environment.php b/lib/Twig/Environment.php index bfd307b..8026e72 100644 --- a/lib/Twig/Environment.php +++ b/lib/Twig/Environment.php @@ -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; diff --git a/lib/Twig/Extension/Escaper.php b/lib/Twig/Extension/Escaper.php index 686cc90..2eedef9 100644 --- a/lib/Twig/Extension/Escaper.php +++ b/lib/Twig/Extension/Escaper.php @@ -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; } diff --git a/lib/Twig/NodeVisitor/Escaper.php b/lib/Twig/NodeVisitor/Escaper.php index d57c307..f442ce7 100644 --- a/lib/Twig/NodeVisitor/Escaper.php +++ b/lib/Twig/NodeVisitor/Escaper.php @@ -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 index 0000000..bb31690 --- /dev/null +++ b/test/Twig/Tests/EnvironmentTest.php @@ -0,0 +1,35 @@ + '{{ foo }} {{ foo }}', + 'js' => '{{ bar }} {{ bar }}', + )); + + $twig = new Twig_Environment($loader, array( + 'debug' => true, + 'cache' => false, + 'autoescape' => array($this, 'escapingStrategyCallback'), + )); + + $this->assertEquals('foo<br/ > foo<br/ >', $twig->render('html', array('foo' => 'foo
'))); + $this->assertEquals('foo\x3cbr\x2f \x3e foo\x3cbr\x2f \x3e', $twig->render('js', array('bar' => 'foo
'))); + } + + public function escapingStrategyCallback($filename) + { + return $filename; + } +} -- 1.7.2.5