mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-16 12:26:30 +00:00
Merge branch '1.x'
* 1.x: adding support for the ?? operator fixed the defined test when used on a constant, a map, or a sequence updated CHANGELOG compare charset strictly
This commit is contained in:
@@ -16,7 +16,10 @@
|
||||
|
||||
* 1.23.4 (2016-XX-XX)
|
||||
|
||||
* adding support for the ?? operator
|
||||
* fixed the defined test when used on a constant, a map, or a sequence
|
||||
* undeprecated _self (should only be used to get the template name, not the template instance)
|
||||
* fixed parsing on PHP7
|
||||
|
||||
* 1.23.3 (2016-01-11)
|
||||
|
||||
|
||||
@@ -794,6 +794,13 @@ The following operators don't fit into any of the other categories:
|
||||
{{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }}
|
||||
{{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}
|
||||
|
||||
* ``??``: The null-coalescing operator:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{# returns the value of foo if it is defined and not null, 'no' otherwise #}
|
||||
{{ foo ?? 'no' }}
|
||||
|
||||
String Interpolation
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
+11
-10
@@ -252,6 +252,7 @@ class Twig_Extension_Core extends Twig_Extension
|
||||
'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
||||
'??' => array('precedence' => 300, 'class' => 'Twig_Node_Expression_NullCoalesce', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -356,7 +357,7 @@ function twig_random(Twig_Environment $env, $values = null)
|
||||
|
||||
$charset = $env->getCharset();
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
$values = iconv($charset, 'UTF-8', $values);
|
||||
}
|
||||
|
||||
@@ -364,7 +365,7 @@ function twig_random(Twig_Environment $env, $values = null)
|
||||
// split at all positions, but not after the start and not before the end
|
||||
$values = preg_split('/(?<!^)(?!$)/u', $values);
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
foreach ($values as $i => $value) {
|
||||
$values[$i] = iconv('UTF-8', $charset, $value);
|
||||
}
|
||||
@@ -823,7 +824,7 @@ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false
|
||||
|
||||
$charset = $env->getCharset();
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
$item = iconv($charset, 'UTF-8', $string);
|
||||
}
|
||||
|
||||
@@ -831,7 +832,7 @@ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false
|
||||
|
||||
$string = implode('', array_reverse($matches[0]));
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
$string = iconv('UTF-8', $charset, $string);
|
||||
}
|
||||
|
||||
@@ -954,7 +955,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
||||
case 'js':
|
||||
// escape all non-alphanumeric characters
|
||||
// into their \xHH or \uHHHH representations
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
$string = iconv($charset, 'UTF-8', $string);
|
||||
}
|
||||
|
||||
@@ -976,14 +977,14 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
||||
return '\\u'.strtoupper(substr('0000'.bin2hex($char), -4));
|
||||
}, $string);
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
$string = iconv('UTF-8', $charset, $string);
|
||||
}
|
||||
|
||||
return $string;
|
||||
|
||||
case 'css':
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
$string = iconv($charset, 'UTF-8', $string);
|
||||
}
|
||||
|
||||
@@ -1010,14 +1011,14 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
||||
return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' ';
|
||||
}, $string);
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
$string = iconv('UTF-8', $charset, $string);
|
||||
}
|
||||
|
||||
return $string;
|
||||
|
||||
case 'html_attr':
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
$string = iconv($charset, 'UTF-8', $string);
|
||||
}
|
||||
|
||||
@@ -1079,7 +1080,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
||||
return sprintf('&#x%s;', $hex);
|
||||
}, $string);
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
if ('UTF-8' !== $charset) {
|
||||
$string = iconv('UTF-8', $charset, $string);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 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_NullCoalesce extends Twig_Node_Expression_Conditional
|
||||
{
|
||||
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
|
||||
{
|
||||
$test = new Twig_Node_Expression_Binary_And(
|
||||
new Twig_Node_Expression_Test_Defined(clone $left, 'defined', new Twig_Node(), $left->getLine()),
|
||||
new Twig_Node_Expression_Unary_Not(new Twig_Node_Expression_Test_Null($left, 'null', new Twig_Node(), $left->getLine()), $left->getLine()),
|
||||
$left->getLine()
|
||||
);
|
||||
|
||||
parent::__construct($test, $left, $right, $lineno);
|
||||
}
|
||||
}
|
||||
@@ -25,17 +25,19 @@ class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
|
||||
{
|
||||
public function __construct(Twig_Node $node, $name, Twig_Node $arguments = null, $lineno)
|
||||
{
|
||||
parent::__construct($node, $name, $arguments, $lineno);
|
||||
|
||||
if ($node instanceof Twig_Node_Expression_Name) {
|
||||
$node->setAttribute('is_defined_test', true);
|
||||
} elseif ($node instanceof Twig_Node_Expression_GetAttr) {
|
||||
$node->setAttribute('is_defined_test', true);
|
||||
|
||||
$this->changeIgnoreStrictCheck($node);
|
||||
} elseif ($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array) {
|
||||
$node = new Twig_Node_Expression_Constant(true, $node->getLine());
|
||||
} else {
|
||||
throw new Twig_Error_Syntax('The "defined" test only works with simple variables.', $this->getLine());
|
||||
}
|
||||
|
||||
parent::__construct($node, $name, $arguments, $lineno);
|
||||
}
|
||||
|
||||
private function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node)
|
||||
|
||||
@@ -26,6 +26,13 @@
|
||||
{{ object.self.foo is defined ? 'ok' : 'ko' }}
|
||||
{{ object.self.undefinedMethod is defined ? 'ko' : 'ok' }}
|
||||
{{ object.undefinedMethod.self is defined ? 'ko' : 'ok' }}
|
||||
{{ 0 is defined ? 'ok' : 'ko' }}
|
||||
{{ "foo" is defined ? 'ok' : 'ko' }}
|
||||
{{ true is defined ? 'ok' : 'ko' }}
|
||||
{{ false is defined ? 'ok' : 'ko' }}
|
||||
{{ null is defined ? 'ok' : 'ko' }}
|
||||
{{ [1, 2] is defined ? 'ok' : 'ko' }}
|
||||
{{ { foo: "bar" } is defined ? 'ok' : 'ko' }}
|
||||
--DATA--
|
||||
return array(
|
||||
'definedVar' => 'defined',
|
||||
@@ -65,6 +72,13 @@ ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
--DATA--
|
||||
return array(
|
||||
'definedVar' => 'defined',
|
||||
@@ -106,3 +120,10 @@ ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
Twig supports the ?? operator
|
||||
--TEMPLATE--
|
||||
{{ 'OK' ?? 'KO' }}
|
||||
{{ null ?? 'OK' }}
|
||||
{{ bar ?? 'KO' }}
|
||||
{{ baz ?? 'OK' }}
|
||||
{{ foo.bar ?? 'KO' }}
|
||||
{{ foo.missing ?? 'OK' }}
|
||||
{{ foo.bar.baz.missing ?? 'OK' }}
|
||||
{{ foo['bar'] ?? 'KO' }}
|
||||
{{ foo['missing'] ?? 'OK' }}
|
||||
{{ nope ?? nada ?? 'OK' }}
|
||||
{{ 1 + nope ?? nada ?? 2 }}
|
||||
{{ 1 + nope ?? 3 + nada ?? 2 }}
|
||||
--DATA--
|
||||
return array('bar' => 'OK', 'foo' => array('bar' => 'OK'))
|
||||
--EXPECT--
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
3
|
||||
6
|
||||
Reference in New Issue
Block a user