2024-06-20 14:10:42 +00:00
< ? 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 .
*/
namespace Twig\Node\Expression ;
use Twig\Compiler ;
2025-01-13 09:56:01 +00:00
use Twig\Node\EmptyNode ;
2024-06-20 14:10:42 +00:00
use Twig\Node\Expression\Binary\AndBinary ;
2025-01-13 09:56:01 +00:00
use Twig\Node\Expression\Binary\NullCoalesceBinary ;
2024-06-20 14:10:42 +00:00
use Twig\Node\Expression\Test\DefinedTest ;
use Twig\Node\Expression\Test\NullTest ;
use Twig\Node\Expression\Unary\NotUnary ;
use Twig\Node\Node ;
2025-01-13 09:56:01 +00:00
use Twig\TwigTest ;
2024-06-20 14:10:42 +00:00
class NullCoalesceExpression extends ConditionalExpression
{
2025-01-13 09:56:01 +00:00
/**
* @ param AbstractExpression $left
* @ param AbstractExpression $right
*/
2024-06-20 14:10:42 +00:00
public function __construct ( Node $left , Node $right , int $lineno )
{
2025-01-13 09:56:01 +00:00
trigger_deprecation ( 'twig/twig' , '3.17' , \sprintf ( '"%s" is deprecated; use "%s" instead.' , __CLASS__ , NullCoalesceBinary :: class ));
if ( ! $left instanceof AbstractExpression ) {
trigger_deprecation ( 'twig/twig' , '3.15' , 'Not passing a "%s" instance to the "left" argument of "%s" is deprecated ("%s" given).' , AbstractExpression :: class , static :: class , \get_class ( $left ));
}
if ( ! $right instanceof AbstractExpression ) {
trigger_deprecation ( 'twig/twig' , '3.15' , 'Not passing a "%s" instance to the "right" argument of "%s" is deprecated ("%s" given).' , AbstractExpression :: class , static :: class , \get_class ( $right ));
}
$test = new DefinedTest ( clone $left , new TwigTest ( 'defined' ), new EmptyNode (), $left -> getTemplateLine ());
2024-06-20 14:10:42 +00:00
// for "block()", we don't need the null test as the return value is always a string
if ( ! $left instanceof BlockReferenceExpression ) {
$test = new AndBinary (
$test ,
2025-01-13 09:56:01 +00:00
new NotUnary ( new NullTest ( $left , new TwigTest ( 'null' ), new EmptyNode (), $left -> getTemplateLine ()), $left -> getTemplateLine ()),
2024-06-20 14:10:42 +00:00
$left -> getTemplateLine ()
);
}
parent :: __construct ( $test , $left , $right , $lineno );
}
public function compile ( Compiler $compiler ) : void
{
/*
* This optimizes only one case . PHP 7 also supports more complex expressions
* that can return null . So , for instance , if log is defined , log ( " foo " ) ? ? " ... " works ,
* but log ( $a [ " foo " ]) ? ? " ... " does not if $a [ " foo " ] is not defined . More advanced
* cases might be implemented as an optimizer node visitor , but has not been done
* as benefits are probably not worth the added complexity .
*/
if ( $this -> getNode ( 'expr2' ) instanceof NameExpression ) {
$this -> getNode ( 'expr2' ) -> setAttribute ( 'always_defined' , true );
$compiler
-> raw ( '((' )
-> subcompile ( $this -> getNode ( 'expr2' ))
-> raw ( ') ?? (' )
-> subcompile ( $this -> getNode ( 'expr3' ))
-> raw ( '))' )
;
} else {
parent :: compile ( $compiler );
}
}
}