From 95d5cefdd7a4d1cc77e3b064537d3c51d1fb847d Mon Sep 17 00:00:00 2001 From: fabien Date: Sun, 13 Dec 2009 13:03:07 +0000 Subject: [PATCH] added the in operator git-svn-id: http://svn.twig-project.org/trunk@170 93ef8e89-cb99-4229-a87c-7fa0fa45744b --- CHANGELOG | 1 + doc/02-Twig-for-Template-Designers.markdown | 18 ++++++++++++++++++ lib/Twig/ExpressionParser.php | 6 +++++- lib/Twig/Node/Expression/Compare.php | 20 ++++++++++++++++++-- test/fixtures/expressions/in.test | 15 +++++++++++++++ test/unit/integrationTest.php | 2 +- 6 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/expressions/in.test diff --git a/CHANGELOG b/CHANGELOG index c5ded3d..ab3187c 100644 --- 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 diff --git a/doc/02-Twig-for-Template-Designers.markdown b/doc/02-Twig-for-Template-Designers.markdown index 6d2709a..72386af 100644 --- a/doc/02-Twig-for-Template-Designers.markdown +++ b/doc/02-Twig-for-Template-Designers.markdown @@ -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 diff --git a/lib/Twig/ExpressionParser.php b/lib/Twig/ExpressionParser.php index 26faba2..b411c69 100644 --- a/lib/Twig/ExpressionParser.php +++ b/lib/Twig/ExpressionParser.php @@ -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()); } diff --git a/lib/Twig/Node/Expression/Compare.php b/lib/Twig/Node/Expression/Compare.php index 71b8e4d..273380a 100644 --- a/lib/Twig/Node/Expression/Compare.php +++ b/lib/Twig/Node/Expression/Compare.php @@ -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 index 0000000..344a97e --- /dev/null +++ b/test/fixtures/expressions/in.test @@ -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 diff --git a/test/unit/integrationTest.php b/test/unit/integrationTest.php index ee05be2..4b89faa 100644 --- a/test/unit/integrationTest.php +++ b/test/unit/integrationTest.php @@ -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) -- 1.7.2.5