2024-06-20 14:10:42 +00:00
< ? php
/*
* This file is part of Twig .
*
* ( c ) Fabien Potencier
* ( c ) Armin Ronacher
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Twig\TokenParser ;
use Twig\Error\SyntaxError ;
use Twig\Node\BlockNode ;
use Twig\Node\BlockReferenceNode ;
use Twig\Node\Node ;
use Twig\Node\PrintNode ;
use Twig\Token ;
/**
* Marks a section of a template as being reusable .
*
* { % block head % }
* < link rel = " stylesheet " href = " style.css " />
* < title > { % block title % }{ % endblock % } - My Webpage </ title >
* { % endblock % }
*
* @ internal
*/
final class BlockTokenParser extends AbstractTokenParser
{
public function parse ( Token $token ) : Node
{
$lineno = $token -> getLine ();
$stream = $this -> parser -> getStream ();
$name = $stream -> expect ( /* Token::NAME_TYPE */ 5 ) -> getValue ();
if ( $this -> parser -> hasBlock ( $name )) {
2024-09-05 17:51:48 +00:00
throw new SyntaxError ( \sprintf ( " The block '%s' has already been defined line %d. " , $name , $this -> parser -> getBlock ( $name ) -> getTemplateLine ()), $stream -> getCurrent () -> getLine (), $stream -> getSourceContext ());
2024-06-20 14:10:42 +00:00
}
$this -> parser -> setBlock ( $name , $block = new BlockNode ( $name , new Node ([]), $lineno ));
$this -> parser -> pushLocalScope ();
$this -> parser -> pushBlockStack ( $name );
if ( $stream -> nextIf ( /* Token::BLOCK_END_TYPE */ 3 )) {
$body = $this -> parser -> subparse ([ $this , 'decideBlockEnd' ], true );
if ( $token = $stream -> nextIf ( /* Token::NAME_TYPE */ 5 )) {
$value = $token -> getValue ();
if ( $value != $name ) {
2024-09-05 17:51:48 +00:00
throw new SyntaxError ( \sprintf ( 'Expected endblock for block "%s" (but "%s" given).' , $name , $value ), $stream -> getCurrent () -> getLine (), $stream -> getSourceContext ());
2024-06-20 14:10:42 +00:00
}
}
} else {
$body = new Node ([
new PrintNode ( $this -> parser -> getExpressionParser () -> parseExpression (), $lineno ),
]);
}
$stream -> expect ( /* Token::BLOCK_END_TYPE */ 3 );
$block -> setNode ( 'body' , $body );
$this -> parser -> popBlockStack ();
$this -> parser -> popLocalScope ();
return new BlockReferenceNode ( $name , $lineno , $this -> getTag ());
}
public function decideBlockEnd ( Token $token ) : bool
{
return $token -> test ( 'endblock' );
}
public function getTag () : string
{
return 'block' ;
}
}