added the in operator
authorfabien <fabien@93ef8e89-cb99-4229-a87c-7fa0fa45744b>
Sun, 13 Dec 2009 13:03:07 +0000 (13:03 +0000)
committerfabien <fabien@93ef8e89-cb99-4229-a87c-7fa0fa45744b>
Sun, 13 Dec 2009 13:03:07 +0000 (13:03 +0000)
git-svn-id: http://svn.twig-project.org/trunk@170 93ef8e89-cb99-4229-a87c-7fa0fa45744b

CHANGELOG
doc/02-Twig-for-Template-Designers.markdown
lib/Twig/ExpressionParser.php
lib/Twig/Node/Expression/Compare.php
test/fixtures/expressions/in.test [new file with mode: 0644]
test/unit/integrationTest.php

index c5ded3d..ab3187c 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,6 @@
 * 0.9.5-DEV
 
+ * added the in operator (as a syntactic sugar for the in filter)
  * added the following filters in the Core extension: in
  * added support for arrays (same behavior as in PHP, a mix between lists and dictionaries, arrays and hashes)
  * enhanced some error messages to provide better feedback in case of parsing errors
index 6d2709a..72386af 100644 (file)
@@ -728,6 +728,11 @@ The following comparison operators are supported in any expression: `==`,
 The following operators are very useful but don't fit into any of the other
 two categories:
 
+ * `in`: Perform containment test. Returns `true` if the left operand is
+   contained in the right. {{ 1 in [1, 2, 3] }} would for example return
+   `true`. To perform a negative test, the whole expression should be prefixed
+   with `not` ({{ not 1 in [1, 2, 3] }} would return `false`).
+
  * `|`: Applies a filter.
 
  * `~`: Converts all operands into strings and concatenates them. `{{ "Hello "
@@ -846,6 +851,19 @@ Returns true if the value is contained within another one.
 You can use this filter to perform a containment test on strings, arrays, or
 objects implementing the `Traversable` interface.
 
+The `in` operator is a syntactic sugar for the `in` filter:
+
+    [twig]
+    {% if 1 in [1, 2, 3] %}
+      TRUE
+    {% endif %}
+
+    {# is equivalent to #}
+
+    {% if 1|in([1, 2, 3]) %}
+      TRUE
+    {% endif %}
+
 ### `default`
 
 The `default` filter returns the passed default value if the value is
index 26faba2..b411c69 100644 (file)
@@ -84,7 +84,11 @@ class Twig_ExpressionParser
     $lineno = $this->parser->getCurrentToken()->getLine();
     $expr = $this->parseAddExpression();
     $ops = array();
-    while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, $operators))
+    while (
+      $this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, $operators)
+      ||
+      $this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'in')
+    )
     {
       $ops[] = array($this->parser->getStream()->next()->getValue(), $this->parseAddExpression());
     }
index 71b8e4d..273380a 100644 (file)
@@ -23,9 +23,14 @@ class Twig_Node_Expression_Compare extends Twig_Node_Expression
 
   public function compile($compiler)
   {
+    $nbOps = count($this->ops) > 1;
+    if ('in' === $this->ops[0][0])
+    {
+      return $this->compileIn($compiler);
+    }
+
     $this->expr->compile($compiler);
     $i = 0;
-    $useTmpVars = count($this->ops) > 1;
     foreach ($this->ops as $op)
     {
       if ($i)
@@ -35,7 +40,7 @@ class Twig_Node_Expression_Compare extends Twig_Node_Expression
       list($op, $node) = $op;
       $compiler->raw(' '.$op.' ');
 
-      if ($useTmpVars)
+      if ($nbOps)
       {
         $compiler
           ->raw('($tmp'.++$i.' = ')
@@ -54,4 +59,15 @@ class Twig_Node_Expression_Compare extends Twig_Node_Expression
       $compiler->raw(')');
     }
   }
+
+  protected function compileIn($compiler)
+  {
+    $compiler
+      ->raw('twig_in_filter(')
+      ->subcompile($this->expr)
+      ->raw(', ')
+      ->subcompile($this->ops[0][1])
+      ->raw(')')
+    ;
+  }
 }
diff --git a/test/fixtures/expressions/in.test b/test/fixtures/expressions/in.test
new file mode 100644 (file)
index 0000000..344a97e
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+Twig supports the in operator
+--TEMPLATE--
+{% if bar in foo %}
+TRUE
+{% endif %}
+{% if not bar in foo %}
+{% else %}
+TRUE
+{% endif %}
+--DATA--
+return array('bar' => 'bar', 'foo' => array('bar' => 'bar'))
+--EXPECT--
+TRUE
+TRUE
index ee05be2..4b89faa 100644 (file)
@@ -33,7 +33,7 @@ class Foo
   }
 }
 
-$t = new LimeTest(53);
+$t = new LimeTest(54);
 $fixturesDir = realpath(dirname(__FILE__).'/../fixtures/');
 
 foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file)