* the include tag now merges the passed variables with the current context by default
(the old behavior is still possible by adding the "only" keyword)
+ * added support for {{ 1 not in [2, 3] }} (more readable than the current {{ not (1 in [2, 3]) }})
* escaping has been rewritten (from pre-escaping to post-escaping)
* the implementation of template inheritance has been rewritten
(blocks can now be called individually and still work with inheritance)
Tests can be negated by prepending them with `not`:
[twig]
+ {% if not (loop.index is divisibleby(3)) %}
+
+ {# also works with an infix notation #}
{% if loop.index is not divisibleby(3) %}
The built-in tests section below describes all the built-in tests.
* `(expr)`: Groups an expression.
+>**NOTE**
+>The `is` and `in` operators support negation using an infix notation too: `foo
+>is not bar` and `foo not in bar` instead of `not (foo is bar)` and `not (foo
+>in bar)`. All other expressions require a prefix notation: `not (foo and
+>bar)`.
+
### Comparisons
The following comparison operators are supported in any expression: `==`,
two categories:
* `in` (new in Twig 0.9.5): Performs containment test. Returns `true` if the
- left operand is contained in the right. {{ 1 in [1, 2, 3] }} would for
+ 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`).
+ should be prefixed with `not` (`{{ not (1 in [1, 2, 3]) }}` would return
+ `false` - can also be written `{{ 1 not in [1, 2, 3] }}`).
* `..` (new in Twig 0.9.5): Creates a sequence based on the operand before
and after the operator (see the `for` tag for some usage examples).
TRUE
{% endif %}
+You can negate an `in` expression with `not`:
+
+ [twig]
+ {% if not (1 in [1, 2, 3]) %}
+
+ {# also works with an infix notation #}
+ {% if 1 not in [1, 2, 3] %}
+
### `range` (new in Twig 0.9.5)
Returns a list containing a sequence of numbers. The left side of the filter
$lineno = $this->parser->getCurrentToken()->getLine();
$expr = $this->parseAddExpression();
$ops = array();
+ $negated = false;
while (
$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, $operators)
||
+ ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'not') && $this->parser->getStream()->look()->test(Twig_Token::NAME_TYPE, 'in'))
+ ||
$this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'in')
) {
+ $this->parser->getStream()->rewind();
+ if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'not')) {
+ $negated = true;
+ $this->parser->getStream()->next();
+ }
$ops[] = new Twig_Node_Expression_Constant($this->parser->getStream()->next()->getValue(), $lineno);
$ops[] = $this->parseAddExpression();
}
return $expr;
}
- return new Twig_Node_Expression_Compare($expr, new Twig_Node($ops), $lineno);
+ $node = new Twig_Node_Expression_Compare($expr, new Twig_Node($ops), $lineno);
+
+ if ($negated) {
+ $node = new Twig_Node_Expression_Unary_Not($node, $lineno);
+ }
+
+ return $node;
}
public function parseAddExpression()