diff --git a/src/Application/UI/Control.php b/src/Application/UI/Control.php index a2b24afeb..72af6eba2 100644 --- a/src/Application/UI/Control.php +++ b/src/Application/UI/Control.php @@ -146,7 +146,7 @@ public function isControlInvalid(?string $snippet = null): bool if ($snippet !== null) { return $this->invalidSnippets[$snippet] ?? isset($this->invalidSnippets["\0"]); - } elseif (count($this->invalidSnippets) > 0) { + } elseif (array_keys($this->invalidSnippets, true, true)) { return true; } diff --git a/src/Bridges/ApplicationLatte/Nodes/ControlNode.php b/src/Bridges/ApplicationLatte/Nodes/ControlNode.php index 2a28c4640..0e5827d23 100644 --- a/src/Bridges/ApplicationLatte/Nodes/ControlNode.php +++ b/src/Bridges/ApplicationLatte/Nodes/ControlNode.php @@ -31,6 +31,7 @@ class ControlNode extends StatementNode public ?ExpressionNode $method = null; public ArrayNode $args; public ?bool $escape = null; + public bool $inSnippetArea = false; public static function create(Tag $tag): static @@ -40,6 +41,7 @@ public static function create(Tag $tag): static $stream = $tag->parser->stream; $node = new static; $node->name = $tag->parser->parseUnquotedStringOrExpression(colon: false); + $node->inSnippetArea = $tag->closestTag(['snippetArea']) && !$tag->closestTag(['snippet']); if ($stream->tryConsume(':')) { $node->method = $tag->parser->parseExpression(); } @@ -94,11 +96,14 @@ public function print(PrintContext $context): string $this->name, ); + $fetchCode .= $this->inSnippetArea + ? 'if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->snippetMode = $this->global->uiControl->snippetMode;' + : 'if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->redrawControl(null, false);'; + if ($this->escape) { return $context->format( <<<'XX' %raw - if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->redrawControl(null, false); ob_start(fn() => ''); $ʟ_tmp->%raw(%args) %line; $ʟ_fi = new LR\FilterInfo(%dump); echo %modifyContent(ob_get_clean()); @@ -117,7 +122,6 @@ public function print(PrintContext $context): string return $context->format( <<<'XX' %raw - if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->redrawControl(null, false); $ʟ_tmp->%raw(%args) %line; diff --git a/src/Bridges/ApplicationLatte/SnippetRuntime.php b/src/Bridges/ApplicationLatte/SnippetRuntime.php index cfd2d9af1..b3737bf8d 100644 --- a/src/Bridges/ApplicationLatte/SnippetRuntime.php +++ b/src/Bridges/ApplicationLatte/SnippetRuntime.php @@ -64,10 +64,11 @@ public function enter(string $name, string $type): void $this->nestingLevel++; } - $this->stack[] = [$name, $obStarted]; - if ($name !== '') { - $this->control->redrawControl($name, false); + $this->stack[] = [$name, $obStarted, $this->control->snippetMode]; + if ($type !== self::TypeArea) { + $this->control->snippetMode = false; } + $this->control->redrawControl($name, false); } @@ -78,7 +79,7 @@ public function leave(): void return; } - [$name, $obStarted] = array_pop($this->stack); + [$name, $obStarted, $this->control->snippetMode] = array_pop($this->stack); if ($this->nestingLevel > 0 && --$this->nestingLevel === 0) { $content = ob_get_clean(); $this->payload ??= $this->control->getPresenter()->getPayload(); @@ -107,7 +108,6 @@ public function renderSnippets(array $blocks, array $params): bool } $this->renderingSnippets = true; - $this->control->snippetMode = false; foreach ($blocks as $name => $block) { if (!$this->control->isControlInvalid($name)) { continue; @@ -117,7 +117,6 @@ public function renderSnippets(array $blocks, array $params): bool $function($params); } - $this->control->snippetMode = true; $this->renderChildren(); return true; } diff --git a/tests/Bridges.Latte3/renderSnippets8.phpt b/tests/Bridges.Latte3/renderSnippets8.phpt new file mode 100644 index 000000000..10b5f5616 --- /dev/null +++ b/tests/Bridges.Latte3/renderSnippets8.phpt @@ -0,0 +1,91 @@ +counter++; + $latte = new Latte\Engine; + $latte->setLoader(new Latte\Loaders\StringLoader); + $latte->addExtension(new Nette\Bridges\ApplicationLatte\UIExtension($this)); + $latte->render('{snippet foo}hello {$arg}{/snippet}', ['arg' => $arg]); + } +} + +class TestPresenter extends Nette\Application\UI\Presenter +{ + public function createComponentTest() + { + return new TestControl; + } + + + public function render() + { + $latte = new Latte\Engine; + $latte->setLoader(new Latte\Loaders\StringLoader); + $latte->addExtension(new Nette\Bridges\ApplicationLatte\UIExtension($this)); + $latte->render('{snippetArea foo}{control test 123}{/snippetArea}'); + } +} + + +$presenter = new TestPresenter; +$presenter->injectPrimary(null, null, null, new Http\Request(new Http\UrlScript('/')), new Http\Response); +$presenter->snippetMode = true; +$presenter->redrawControl('foo'); +$presenter['test']->redrawControl('foo'); +$presenter->render(); +Assert::same([ + 'snippets' => [ + 'snippet-test-foo' => 'hello 123', + ], +], (array) $presenter->payload); +Assert::same(1, $presenter['test']->counter); + + +$presenter = new TestPresenter; +$presenter->injectPrimary(null, null, null, new Http\Request(new Http\UrlScript('/')), new Http\Response); +$presenter->snippetMode = true; +$presenter->redrawControl('foo'); +$presenter['test']->redrawControl(); +$presenter->render(); +Assert::same([ + 'snippets' => [ + 'snippet-test-foo' => 'hello 123', + ], +], (array) $presenter->payload); +Assert::same(2, $presenter['test']->counter); + + +$presenter = new TestPresenter; +$presenter->injectPrimary(null, null, null, new Http\Request(new Http\UrlScript('/')), new Http\Response); +$presenter->snippetMode = true; +$presenter['test']->redrawControl('foo'); +$presenter->render(); +Assert::same([ + 'snippets' => [ + 'snippet-test-foo' => 'hello 0', + ], +], (array) $presenter->payload); +Assert::same(1, $presenter['test']->counter);