1515use Latte \Compiler \Nodes \StatementNode ;
1616use Latte \Compiler \PrintContext ;
1717use Latte \Compiler \Tag ;
18+ use function in_array ;
1819
1920
2021/**
21- * {form name [, attributes]} ... {/form}
22+ * {form [scope] name [, attributes]} ... {/form}
2223 * {formContext name} ... {/formContext}
2324 * Renders form tags and initializes form context.
2425 */
2526class FormNode extends StatementNode
2627{
28+ private const ModeLegacyScope = 'context ' ;
29+ private const ModeScope = 'scope ' ;
30+
2731 public ExpressionNode $ name ;
2832 public ArrayNode $ attributes ;
2933 public AreaNode $ content ;
30- public bool $ print ;
34+ public ? string $ mode = null ;
3135
3236
3337 /** @return \Generator<int, ?list<string>, array{AreaNode, ?Tag}, static> */
@@ -40,13 +44,21 @@ public static function create(Tag $tag): \Generator
4044 $ tag ->outputMode = $ tag ::OutputKeepIndentation;
4145 $ tag ->expectArguments ();
4246 $ node = $ tag ->node = new static ;
47+ $ node ->mode = match (true ) {
48+ $ tag ->name === 'formContext ' => self ::ModeLegacyScope,
49+ in_array ($ tag ->parser ->stream ->tryPeek ()?->text, [self ::ModeScope], strict: true ) => $ tag ->parser ->stream ->consume ()->text ,
50+ default => null ,
51+ };
4352 $ node ->name = $ tag ->parser ->parseUnquotedStringOrExpression ();
4453 if (!$ tag ->parser ->stream ->tryConsume (', ' ) && !$ tag ->parser ->isEnd ()) {
4554 $ position = $ tag ->parser ->stream ->peek ()->position ;
4655 trigger_error ("Missing comma before arguments in { {$ tag ->name }} tag $ position. " , E_USER_DEPRECATED );
4756 }
4857 $ node ->attributes = $ tag ->parser ->parseArguments ();
49- $ node ->print = $ tag ->name === 'form ' ;
58+ if ($ node ->mode !== null && $ node ->attributes ->items ) {
59+ $ label = '{ ' . $ tag ->name . ($ node ->mode === self ::ModeScope ? ' scope ' : '' ) . '} ' ;
60+ throw new CompileException ("Arguments are not allowed in $ label because it does not render a <form> tag. " , $ tag ->position );
61+ }
5062
5163 [$ node ->content , $ endTag ] = yield ;
5264 if ($ endTag && $ node ->name instanceof StringNode) {
@@ -59,19 +71,21 @@ public static function create(Tag $tag): \Generator
5971
6072 public function print (PrintContext $ context ): string
6173 {
74+ $ renderBegin = 'echo $this->global->forms->renderFormBegin(%node) %1.line; ' ;
75+ $ renderEnd = 'echo $this->global->forms->renderFormEnd() %4.line; ' ;
76+
6277 return $ context ->format (
6378 '$this->global->forms->begin($form = '
64- . ($ this ->name instanceof StringNode
65- ? '$this->global->uiControl[%node] '
66- : '(is_object($ʟ_tmp = %node) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp]) ' )
79+ . (match (true ) {
80+ $ this ->mode === self ::ModeScope => '(is_object($ʟ_tmp = %node) ? $ʟ_tmp : ($this->global->forms->isNested() ? $this->global->forms->get($ʟ_tmp, Nette\Forms\Container::class) : $this->global->uiControl[$ʟ_tmp])) ' ,
81+ $ this ->name instanceof StringNode => '$this->global->uiControl[%node] ' ,
82+ default => '(is_object($ʟ_tmp = %node) ? $ʟ_tmp : $this->global->uiControl[$ʟ_tmp]) ' ,
83+ })
6784 . ') %line; '
68- . ($ this ->print
69- ? 'echo $this->global->forms->renderFormBegin(%node) %1.line; '
70- : '' )
71- . ' %3.node '
72- . ($ this ->print
73- ? 'echo $this->global->forms->renderFormEnd() %4.line; '
74- : '' )
85+ . (match ($ this ->mode ) {
86+ self ::ModeScope, self ::ModeLegacyScope => ' %3.node ' ,
87+ default => $ renderBegin . ' %3.node ' . $ renderEnd ,
88+ })
7589 . '$this->global->forms->end(); '
7690 . "\n\n" ,
7791 $ this ->name ,
0 commit comments