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 ;
use Twig\Attribute\YieldReady ;
use Twig\Compiler ;
use Twig\Error\SyntaxError ;
2025-01-13 09:56:01 +00:00
use Twig\Node\Expression\ArrayExpression ;
use Twig\Node\Expression\Variable\LocalVariable ;
2024-06-20 14:10:42 +00:00
/**
* Represents a macro node .
*
* @ author Fabien Potencier < fabien @ symfony . com >
*/
#[YieldReady]
class MacroNode extends Node
{
public const VARARGS_NAME = 'varargs' ;
2025-01-13 09:56:01 +00:00
/**
* @ param BodyNode $body
* @ param ArrayExpression $arguments
*/
public function __construct ( string $name , Node $body , Node $arguments , int $lineno )
2024-06-20 14:10:42 +00:00
{
2025-01-13 09:56:01 +00:00
if ( ! $body instanceof BodyNode ) {
trigger_deprecation ( 'twig/twig' , '3.12' , \sprintf ( 'Not passing a "%s" instance as the "body" argument of the "%s" constructor is deprecated ("%s" given).' , BodyNode :: class , static :: class , $body :: class ));
}
if ( ! $arguments instanceof ArrayExpression ) {
trigger_deprecation ( 'twig/twig' , '3.15' , \sprintf ( 'Not passing a "%s" instance as the "arguments" argument of the "%s" constructor is deprecated ("%s" given).' , ArrayExpression :: class , static :: class , $arguments :: class ));
$args = new ArrayExpression ([], $arguments -> getTemplateLine ());
foreach ( $arguments as $n => $default ) {
$args -> addElement ( $default , new LocalVariable ( $n , $default -> getTemplateLine ()));
}
$arguments = $args ;
}
foreach ( $arguments -> getKeyValuePairs () as $pair ) {
if ( " \ u { 035C} " . self :: VARARGS_NAME === $pair [ 'key' ] -> getAttribute ( 'name' )) {
throw new SyntaxError ( \sprintf ( 'The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.' , self :: VARARGS_NAME , $name , self :: VARARGS_NAME ), $pair [ 'value' ] -> getTemplateLine (), $pair [ 'value' ] -> getSourceContext ());
2024-06-20 14:10:42 +00:00
}
}
2025-01-13 09:56:01 +00:00
parent :: __construct ([ 'body' => $body , 'arguments' => $arguments ], [ 'name' => $name ], $lineno );
2024-06-20 14:10:42 +00:00
}
public function compile ( Compiler $compiler ) : void
{
$compiler
-> addDebugInfo ( $this )
2024-09-05 17:51:48 +00:00
-> write ( \sprintf ( 'public function macro_%s(' , $this -> getAttribute ( 'name' )))
2024-06-20 14:10:42 +00:00
;
2025-01-13 09:56:01 +00:00
/** @var ArrayExpression $arguments */
$arguments = $this -> getNode ( 'arguments' );
foreach ( $arguments -> getKeyValuePairs () as $pair ) {
$name = $pair [ 'key' ];
$default = $pair [ 'value' ];
2024-06-20 14:10:42 +00:00
$compiler
2025-01-13 09:56:01 +00:00
-> subcompile ( $name )
-> raw ( ' = ' )
2024-06-20 14:10:42 +00:00
-> subcompile ( $default )
2025-01-13 09:56:01 +00:00
-> raw ( ', ' )
2024-06-20 14:10:42 +00:00
;
}
$compiler
2025-01-13 09:56:01 +00:00
-> raw ( '...$varargs' )
-> raw ( " ): string|Markup \n " )
2024-06-20 14:10:42 +00:00
-> write ( " { \n " )
-> indent ()
-> write ( " \$ macros = \$ this->macros; \n " )
2025-01-13 09:56:01 +00:00
-> write ( " \$ context = [ \n " )
2024-06-20 14:10:42 +00:00
-> indent ()
;
2025-01-13 09:56:01 +00:00
foreach ( $arguments -> getKeyValuePairs () as $pair ) {
$name = $pair [ 'key' ];
$var = $name -> getAttribute ( 'name' );
if ( str_starts_with ( $var , " \ u { 035C} " )) {
$var = substr ( $var , \strlen ( " \ u { 035C} " ));
}
2024-06-20 14:10:42 +00:00
$compiler
-> write ( '' )
2025-01-13 09:56:01 +00:00
-> string ( $var )
-> raw ( ' => ' )
-> subcompile ( $name )
2024-06-20 14:10:42 +00:00
-> raw ( " , \n " )
;
}
2025-01-13 09:56:01 +00:00
$node = new CaptureNode ( $this -> getNode ( 'body' ), $this -> getNode ( 'body' ) -> lineno );
2024-06-20 14:10:42 +00:00
$compiler
-> write ( '' )
-> string ( self :: VARARGS_NAME )
-> raw ( ' => ' )
2025-01-13 09:56:01 +00:00
-> raw ( " \$ varargs, \n " )
2024-06-20 14:10:42 +00:00
-> outdent ()
2025-01-13 09:56:01 +00:00
-> write ( " ] + \$ this->env->getGlobals(); \n \n " )
2024-06-20 14:10:42 +00:00
-> write ( " \$ blocks = []; \n \n " )
-> write ( 'return ' )
-> subcompile ( $node )
-> raw ( " \n " )
-> outdent ()
-> write ( " } \n \n " )
;
}
}