fixed default() filter behavior when used with strict_variables set to on
authorFabien Potencier <fabien.potencier@gmail.com>
Tue, 14 Dec 2010 13:27:28 +0000 (14:27 +0100)
committerFabien Potencier <fabien.potencier@gmail.com>
Tue, 14 Dec 2010 13:27:28 +0000 (14:27 +0100)
CHANGELOG
lib/Twig/Node/Expression/Filter.php
lib/Twig/Node/Expression/Test.php
test/Twig/Tests/Fixtures/filters/default.test

index dda3a2f..397decd 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,7 @@ Backward incompatibilities:
 
 Changes:
 
+ * fixed default() filter behavior when used with strict_variables set to on
  * fixed filesystem loader compatibility with PHAR files
  * enhanced error messages when an unexpected token is parsed in an expression
  * fixed filename not being added to syntax error messages
index 33223d5..3a29548 100644 (file)
  */
 class Twig_Node_Expression_Filter extends Twig_Node_Expression
 {
-    public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filter_name, Twig_NodeInterface $arguments, $lineno, $tag = null)
+    public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
     {
-        parent::__construct(array('node' => $node, 'filter' => $filter_name, 'arguments' => $arguments), array(), $lineno, $tag);
+        parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag);
     }
 
     public function compile($compiler)
     {
         $filterMap = $compiler->getEnvironment()->getFilters();
-
         $name = $this->getNode('filter')->getAttribute('value');
-        $attrs = $this->getNode('arguments');
-
         if (!isset($filterMap[$name])) {
             throw new Twig_Error_Syntax(sprintf('The filter "%s" does not exist', $name), $this->getLine());
+        }
+        $filter = $filterMap[$name];
+
+        // foo|default('bar') or foo.bar|default('bar')
+        // compiled to {{ foo is defined ? foo|default('bar') : 'bar' }}
+        if ('default' === $name && ($this->getNode('node') instanceof Twig_Node_Expression_Name || $this->getNode('node') instanceof Twig_Node_Expression_GetAttr)) {
+            if ($this->getNode('node') instanceof Twig_Node_Expression_Name) {
+                $testMap = $compiler->getEnvironment()->getTests();
+                $compiler
+                    ->raw($testMap['defined']->compile().'(')
+                    ->repr($this->getNode('node')->getAttribute('name'))
+                    ->raw(', $context)')
+                ;
+            } elseif ($this->getNode('node') instanceof Twig_Node_Expression_GetAttr) {
+                $this->getNode('node')->setAttribute('is_defined_test', true);
+                $compiler->subcompile($this->getNode('node'));
+            }
+
+            $compiler->raw(' ? ');
+            $this->compileFilter($compiler, $filter);
+            $compiler->raw(' : ');
+            $compiler->subcompile($this->getNode('arguments')->getNode(0));
         } else {
-            $compiler->raw($filterMap[$name]->compile().($filterMap[$name]->needsEnvironment() ? '($this->env, ' : '('));
+            $this->compileFilter($compiler, $filter);
         }
+    }
+
+    protected function compileFilter($compiler, $filter)
+    {
+        $compiler->raw($filter->compile().($filter->needsEnvironment() ? '($this->env, ' : '('));
 
         $this->getNode('node')->compile($compiler);
 
-        foreach ($attrs as $node) {
+        foreach ($this->getNode('arguments') as $node) {
             $compiler
                 ->raw(', ')
                 ->subcompile($node)
-                ;
+            ;
         }
 
         $compiler->raw(')');
index 2ab9aa2..8ef498c 100644 (file)
@@ -26,7 +26,7 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression
         if ('defined' === $this->getAttribute('name')) {
             if ($this->getNode('node') instanceof Twig_Node_Expression_Name) {
                 $compiler
-                    ->raw($testMap[$this->getAttribute('name')]->compile().'(')
+                    ->raw($testMap['defined']->compile().'(')
                     ->repr($this->getNode('node')->getAttribute('name'))
                     ->raw(', $context)')
                 ;
index 8fd8017..0c975dd 100644 (file)
@@ -3,8 +3,10 @@
 --TEMPLATE--
 {{ foo|default('bar') }}
 {{ bar|default('foo') }}
+{{ not_defined|default('bar') }}
 --DATA--
 return array('foo' => null, 'bar' => 'bar')
 --EXPECT--
 bar
 bar
+bar