From cdd57f33b53fb664b26418f2406e2b048d903ca6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 25 Jan 2016 16:48:27 +0100 Subject: [PATCH] adding support for the ?? operator --- CHANGELOG | 1 + doc/templates.rst | 7 +++++ lib/Twig/Extension/Core.php | 1 + lib/Twig/Node/Expression/NullCoalesce.php | 23 ++++++++++++++ .../Tests/Fixtures/tests/null_coalesce.test | 30 +++++++++++++++++++ 5 files changed, 62 insertions(+) create mode 100644 lib/Twig/Node/Expression/NullCoalesce.php create mode 100644 test/Twig/Tests/Fixtures/tests/null_coalesce.test diff --git a/CHANGELOG b/CHANGELOG index ccd2765a1b..d3713d0b7a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ * 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 diff --git a/doc/templates.rst b/doc/templates.rst index 62d13e4a69..36a0a7fa6b 100644 --- a/doc/templates.rst +++ b/doc/templates.rst @@ -808,6 +808,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 ~~~~~~~~~~~~~~~~~~~~ diff --git a/lib/Twig/Extension/Core.php b/lib/Twig/Extension/Core.php index de55b38715..79ef5210ad 100644 --- a/lib/Twig/Extension/Core.php +++ b/lib/Twig/Extension/Core.php @@ -261,6 +261,7 @@ public function getOperators() '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), ), ); } diff --git a/lib/Twig/Node/Expression/NullCoalesce.php b/lib/Twig/Node/Expression/NullCoalesce.php new file mode 100644 index 0000000000..10039130cf --- /dev/null +++ b/lib/Twig/Node/Expression/NullCoalesce.php @@ -0,0 +1,23 @@ +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); + } +} diff --git a/test/Twig/Tests/Fixtures/tests/null_coalesce.test b/test/Twig/Tests/Fixtures/tests/null_coalesce.test new file mode 100644 index 0000000000..3d148c893d --- /dev/null +++ b/test/Twig/Tests/Fixtures/tests/null_coalesce.test @@ -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