2626 */
2727class IncludeBlockNode extends StatementNode
2828{
29- public ExpressionNode $ name ;
29+ /** null in {include parent}/{include this} inside a dynamically named block; the name is taken from the runtime */
30+ public ?ExpressionNode $ name = null ;
3031 public ?ExpressionNode $ from = null ;
3132 public ArrayNode $ args ;
3233 public ModifierNode $ modifier ;
@@ -64,14 +65,17 @@ public static function create(Tag $tag, TemplateParser $parser): static
6465 $ item = $ tag ->closestTag (
6566 [BlockNode::class, DefineNode::class],
6667 fn ($ item ) => ($ item ->node instanceof BlockNode || $ item ->node instanceof DefineNode)
67- && $ item ->node ->block && !$ item ->node ->block ->isDynamic (),
68+ && $ item ->node ->block
69+ && (!$ item ->node ->block ->isDynamic () || !$ node ->from ),
6870 );
6971 if (!$ item || !($ item ->node instanceof BlockNode || $ item ->node instanceof DefineNode)) {
7072 throw new CompileException ("Cannot include $ tokenName ->text block outside of any block. " , $ tag ->position );
7173 }
7274
7375 assert ($ item ->node ->block !== null );
74- $ node ->name = $ item ->node ->block ->name ;
76+ $ node ->name = $ item ->node ->block ->isDynamic ()
77+ ? null // the name of the enclosing block is known only at runtime
78+ : $ item ->node ->block ->name ;
7579 }
7680
7781 $ node ->modifier ->escape = !$ node ->modifier ->removeFilter ('noescape ' ) && !$ node ->parent ;
@@ -106,9 +110,9 @@ private function printBlock(PrintContext $context, string $contentFilter): strin
106110 return $ context ->format (
107111 '$this->render ' . ($ this ->parent ? 'ParentBlock ' : 'Block ' )
108112 . '(%raw, %node? + '
109- . (isset ($ block ) && !$ block ->parameters ? 'get_defined_vars() ' : '[] ' )
113+ . ($ this -> name === null || ( isset ($ block ) && !$ block ->parameters ) ? 'get_defined_vars() ' : '[] ' )
110114 . '%raw) %line; ' ,
111- $ context ->ensureString ($ this ->name , 'Block name ' ),
115+ $ this -> name === null ? ' null ' : $ context ->ensureString ($ this ->name , 'Block name ' ),
112116 $ this ->args ,
113117 $ contentFilter ? ", $ contentFilter " : '' ,
114118 $ this ->position ,
@@ -118,7 +122,7 @@ private function printBlock(PrintContext $context, string $contentFilter): strin
118122
119123 private function printBlockFrom (PrintContext $ context , string $ contentFilter ): string
120124 {
121- assert ($ this ->from !== null );
125+ assert ($ this ->from !== null && $ this -> name !== null );
122126 return $ context ->format (
123127 '$this->createTemplate(%raw, %node? + $this->params, "include")->renderToContentType(%raw, %raw) %line; ' ,
124128 $ context ->ensureString ($ this ->from , 'Template name ' ),
@@ -132,7 +136,9 @@ private function printBlockFrom(PrintContext $context, string $contentFilter): s
132136
133137 public function &getIterator (): \Generator
134138 {
135- yield $ this ->name ;
139+ if ($ this ->name ) {
140+ yield $ this ->name ;
141+ }
136142 if ($ this ->from ) {
137143 yield $ this ->from ;
138144 }
0 commit comments