added a Twig_Node_Expression_DefaultFilter to replace the current way of dealing...
authorFabien Potencier <fabien.potencier@gmail.com>
Sun, 16 Oct 2011 03:46:09 +0000 (05:46 +0200)
committerFabien Potencier <fabien.potencier@gmail.com>
Sun, 16 Oct 2011 03:46:09 +0000 (05:46 +0200)
lib/Twig/ExpressionParser.php
lib/Twig/Node/Expression/DefaultFilter.php [new file with mode: 0644]

index b7ff70d..e218e40 100644 (file)
@@ -320,14 +320,8 @@ 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 (Twig_Node_Expression_DefaultFilter::isDefaultFilter($node)) {
+                $node = new Twig_Node_Expression_DefaultFilter($node);
             }
 
             if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) {
diff --git a/lib/Twig/Node/Expression/DefaultFilter.php b/lib/Twig/Node/Expression/DefaultFilter.php
new file mode 100644 (file)
index 0000000..b184f1e
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+class Twig_Node_Expression_DefaultFilter extends Twig_Node_Expression
+{
+    public function __construct(Twig_Node_Expression_Filter $node)
+    {
+        if (!self::isDefaultFilter($node)) {
+            throw new Twig_Error('The default filter node cannot be created from the given node.', $node->getLine());
+        }
+
+        $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());
+
+        parent::__construct(array('node' => $node), array(), $node->getLine());
+    }
+
+    public function compile(Twig_Compiler $compiler)
+    {
+        $compiler->subcompile($this->getNode('node'));
+    }
+
+    /**
+     * Checks whether a node is a default filter that needs to be wrapped with Twig_Node_Expression_DefaultFilter.
+     *
+     * The default filter needs to be wrapped with an instance of Twig_Node_Expression_DefaultFilter
+     * 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' }}
+     *
+     * @param Twig_NodeInterface $node A Twig_NodeInterface instance
+     *
+     * @return Boolean true if the node must be wrapped with a Twig_Node_Expression_DefaultFilter, false otherwise
+     */
+    static public function isDefaultFilter(Twig_NodeInterface $node)
+    {
+        return $node instanceof Twig_Node_Expression_Filter && 'default' === $node->getNode('filter')->getAttribute('value') && ($node->getNode('node') instanceof Twig_Node_Expression_Name || $node->getNode('node') instanceof Twig_Node_Expression_GetAttr);
+    }
+}