From 4a91f4ff34f6d704773ca6300758a928394bfe85 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 6 Oct 2011 16:37:14 +0200 Subject: [PATCH] refactored 'defined' test and 'default' filter Node manipulations have been moved outside the compile() method. That's needed if we want to be able to visit all nodes that will be compiled. --- lib/Twig/ExpressionParser.php | 10 ++++++++++ lib/Twig/Node/Expression/Filter.php | 27 +-------------------------- lib/Twig/Node/Expression/Test.php | 18 +++++++++++------- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/lib/Twig/ExpressionParser.php b/lib/Twig/ExpressionParser.php index 97c8431..b7ff70d 100644 --- a/lib/Twig/ExpressionParser.php +++ b/lib/Twig/ExpressionParser.php @@ -320,6 +320,16 @@ class Twig_ExpressionParser $node = new Twig_Node_Expression_Filter($node, $name, $arguments, $token->getLine(), $tag); + // The default filter is intercepted when the filtered value + // is a name (like obj) or an attribute (like obj.attr) + // In such a case, it's compiled to {{ obj is defined ? obj|default('bar') : 'bar' }} + if ('default' === $token->getValue() && ($node->getNode('node') instanceof Twig_Node_Expression_Name || $node->getNode('node') instanceof Twig_Node_Expression_GetAttr)) { + $test = new Twig_Node_Expression_Test(clone $node->getNode('node'), 'defined', new Twig_Node(), $node->getLine()); + $default = count($node->getNode('arguments')) ? $node->getNode('arguments')->getNode(0) : new Twig_Node_Expression_Constant('', $node->getLine()); + + $node = new Twig_Node_Expression_Conditional($test, $node, $default, $node->getLine()); + } + if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) { break; } diff --git a/lib/Twig/Node/Expression/Filter.php b/lib/Twig/Node/Expression/Filter.php index 101e6df..bff1a67 100644 --- a/lib/Twig/Node/Expression/Filter.php +++ b/lib/Twig/Node/Expression/Filter.php @@ -23,32 +23,7 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression throw new Twig_Error_Syntax(sprintf('The filter "%s" does not exist', $name), $this->getLine()); } - $node = $this->getNode('node'); - - // The default filter is intercepted when the filtered value - // is a name (like obj) or an attribute (like obj.attr) - // In such a case, it's compiled to {{ obj is defined ? obj|default('bar') : 'bar' }} - if ('default' === $name && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) { - $compiler - ->raw('((') - ->subcompile(new Twig_Node_Expression_Test($node, 'defined', new Twig_Node(), $this->getLine())) - ->raw(') ? (') - ; - - $this->compileFilter($compiler, $filter); - - $compiler->raw(') : ('); - - if ($this->getNode('arguments')->hasNode(0)) { - $compiler->subcompile($this->getNode('arguments')->getNode(0)); - } else { - $compiler->string(''); - } - - $compiler->raw('))'); - } else { - $this->compileFilter($compiler, $filter); - } + $this->compileFilter($compiler, $filter); } protected function compileFilter(Twig_Compiler $compiler, Twig_FilterInterface $filter) diff --git a/lib/Twig/Node/Expression/Test.php b/lib/Twig/Node/Expression/Test.php index ef35df6..1c000ac 100644 --- a/lib/Twig/Node/Expression/Test.php +++ b/lib/Twig/Node/Expression/Test.php @@ -13,6 +13,15 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) { parent::__construct(array('node' => $node, 'arguments' => $arguments), array('name' => $name), $lineno); + + // defined is a special case + if ('defined' === $name) { + if ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr) { + $node->setAttribute('is_defined_test', true); + } else { + throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine()); + } + } } public function compile(Twig_Compiler $compiler) @@ -27,13 +36,8 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression // defined is a special case if ('defined' === $name) { - if ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr) { - $node->setAttribute('is_defined_test', true); - $compiler->subcompile($node); - $node->removeAttribute('is_defined_test'); - } else { - throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine()); - } + $compiler->subcompile($node); + return; } -- 1.7.2.5