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\Test ;
2025-01-13 09:56:01 +00:00
use Twig\Attribute\FirstClassTwigCallableReady ;
2024-06-20 14:10:42 +00:00
use Twig\Compiler ;
use Twig\Error\SyntaxError ;
2025-01-13 09:56:01 +00:00
use Twig\Node\Expression\AbstractExpression ;
2024-06-20 14:10:42 +00:00
use Twig\Node\Expression\ArrayExpression ;
use Twig\Node\Expression\BlockReferenceExpression ;
use Twig\Node\Expression\ConstantExpression ;
use Twig\Node\Expression\FunctionExpression ;
use Twig\Node\Expression\GetAttrExpression ;
2025-01-13 09:56:01 +00:00
use Twig\Node\Expression\MacroReferenceExpression ;
2024-06-20 14:10:42 +00:00
use Twig\Node\Expression\MethodCallExpression ;
use Twig\Node\Expression\NameExpression ;
use Twig\Node\Expression\TestExpression ;
use Twig\Node\Node ;
2025-01-13 09:56:01 +00:00
use Twig\TwigTest ;
2024-06-20 14:10:42 +00:00
/**
* Checks if a variable is defined in the current context .
*
* { # defined works with variable names and variable attributes #}
* { % if foo is defined % }
* { # ... #}
* { % endif % }
*
* @ author Fabien Potencier < fabien @ symfony . com >
*/
class DefinedTest extends TestExpression
{
2025-01-13 09:56:01 +00:00
/**
* @ param AbstractExpression $node
*/
#[FirstClassTwigCallableReady]
public function __construct ( Node $node , TwigTest | string $name , ? Node $arguments , int $lineno )
2024-06-20 14:10:42 +00:00
{
2025-01-13 09:56:01 +00:00
if ( ! $node instanceof AbstractExpression ) {
trigger_deprecation ( 'twig/twig' , '3.15' , 'Not passing a "%s" instance to the "node" argument of "%s" is deprecated ("%s" given).' , AbstractExpression :: class , static :: class , \get_class ( $node ));
}
2024-06-20 14:10:42 +00:00
if ( $node instanceof NameExpression ) {
$node -> setAttribute ( 'is_defined_test' , true );
} elseif ( $node instanceof GetAttrExpression ) {
$node -> setAttribute ( 'is_defined_test' , true );
$this -> changeIgnoreStrictCheck ( $node );
} elseif ( $node instanceof BlockReferenceExpression ) {
$node -> setAttribute ( 'is_defined_test' , true );
2025-01-13 09:56:01 +00:00
} elseif ( $node instanceof MacroReferenceExpression ) {
$node -> setAttribute ( 'is_defined_test' , true );
2024-06-20 14:10:42 +00:00
} elseif ( $node instanceof FunctionExpression && 'constant' === $node -> getAttribute ( 'name' )) {
$node -> setAttribute ( 'is_defined_test' , true );
} elseif ( $node instanceof ConstantExpression || $node instanceof ArrayExpression ) {
$node = new ConstantExpression ( true , $node -> getTemplateLine ());
} elseif ( $node instanceof MethodCallExpression ) {
$node -> setAttribute ( 'is_defined_test' , true );
} else {
throw new SyntaxError ( 'The "defined" test only works with simple variables.' , $lineno );
}
2025-01-13 09:56:01 +00:00
if ( \is_string ( $name ) && 'defined' !== $name ) {
trigger_deprecation ( 'twig/twig' , '3.12' , 'Creating a "DefinedTest" instance with a test name that is not "defined" is deprecated.' );
}
2024-06-20 14:10:42 +00:00
parent :: __construct ( $node , $name , $arguments , $lineno );
}
private function changeIgnoreStrictCheck ( GetAttrExpression $node )
{
$node -> setAttribute ( 'optimizable' , false );
$node -> setAttribute ( 'ignore_strict_check' , true );
if ( $node -> getNode ( 'node' ) instanceof GetAttrExpression ) {
$this -> changeIgnoreStrictCheck ( $node -> getNode ( 'node' ));
}
}
public function compile ( Compiler $compiler ) : void
{
$compiler -> subcompile ( $this -> getNode ( 'node' ));
}
}