Skip to content

Commit ad84cf7

Browse files
committed
[TwigComponent] Fix Live embedded component with namespace
1 parent 14115f1 commit ad84cf7

File tree

4 files changed

+67
-18
lines changed

4 files changed

+67
-18
lines changed

src/LiveComponent/tests/Functional/EventListener/LiveComponentSubscriberTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,45 @@ public function testItUseBlocksFromEmbeddedContextUsingMultipleComponents(): voi
311311
;
312312
}
313313

314+
public function testItUseBlocksFromEmbeddedContextUsingMultipleComponentsWithNamespacedTemplate(): void
315+
{
316+
$templateName = 'render_multiple_embedded_with_blocks.html.twig';
317+
$obscuredName = '5c474b02358c46cca3da7340cc79cc2e';
318+
319+
$this->addTemplateMap($obscuredName, $templateName);
320+
321+
$dehydrated = $this->dehydrateComponent(
322+
$this->mountComponent(
323+
'component2',
324+
[
325+
'data-host-template' => $obscuredName,
326+
'data-embedded-template-index' => self::DETERMINISTIC_ID_MULTI_2,
327+
]
328+
)
329+
);
330+
331+
$token = null;
332+
333+
$this->browser()
334+
->visit('/render-namespaced-template/render_multiple_embedded_with_blocks')
335+
->assertSuccessful()
336+
->assertSeeIn('#component1', 'Overridden content from component 1')
337+
->assertSeeIn('#component2', 'Overridden content from component 2 on same line - count: 1')
338+
->assertSeeIn('#component3', 'PreReRenderCalled: No')
339+
->use(function (Crawler $crawler) use (&$token) {
340+
// get a valid token to use for actions
341+
$token = $crawler->filter('div')->eq(1)->attr('data-live-csrf-value');
342+
})
343+
->post('/_components/component2/increase', [
344+
'headers' => ['X-CSRF-TOKEN' => $token],
345+
'body' => ['data' => json_encode(['props' => $dehydrated->getProps()])],
346+
])
347+
->assertSuccessful()
348+
->assertHeaderContains('Content-Type', 'html')
349+
->assertSee('Overridden content from component 2 on same line - count: 2')
350+
;
351+
}
352+
314353
public function testCanRedirectFromComponentAction(): void
315354
{
316355
$dehydrated = $this->dehydrateComponent($this->mountComponent('component2'));

src/TwigComponent/src/Twig/ComponentNode.php

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function compile(Compiler $compiler): void
6868
->raw('), ')
6969
->raw($this->getAttribute('only') ? '[]' : '$context')
7070
->raw(', ')
71-
->string($this->parseTemplateName($this->getAttribute('name')))
71+
->string(TemplateNameParser::parse($this->getAttribute('name')))
7272
->raw(', ')
7373
->raw($this->getAttribute('index'))
7474
->raw(");\n")
@@ -91,20 +91,4 @@ public function compile(Compiler $compiler): void
9191
->raw("\n")
9292
;
9393
}
94-
95-
/**
96-
* Copied from Twig\Loader\FilesystemLoader, and adjusted to needs for this class.
97-
*/
98-
private function parseTemplateName(string $name): mixed
99-
{
100-
if (isset($name[0]) && '@' == $name[0]) {
101-
if (false === $pos = strpos($name, '/')) {
102-
throw new \LogicException(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
103-
}
104-
105-
return substr($name, $pos + 1);
106-
}
107-
108-
return $name;
109-
}
11094
}

src/TwigComponent/src/Twig/ComponentTokenParser.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function parse(Token $token): Node
8787
$this->parser->embedTemplate($module);
8888

8989
// use deterministic index for the embedded template, so it can be loaded in a controlled manner
90-
$module->setAttribute('index', $this->generateEmbeddedTemplateIndex($stream->getSourceContext()->getName(), $token->getLine()));
90+
$module->setAttribute('index', $this->generateEmbeddedTemplateIndex(TemplateNameParser::parse($stream->getSourceContext()->getName()), $token->getLine()));
9191

9292
$stream->expect(Token::BLOCK_END_TYPE);
9393

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Symfony\UX\TwigComponent\Twig;
6+
7+
final class TemplateNameParser
8+
{
9+
/**
10+
* Copied from Twig\Loader\FilesystemLoader, and adjusted to needs for this class (no namespace returned).
11+
*
12+
* @see \Twig\Loader\FilesystemLoader::parseName
13+
*/
14+
public static function parse(string $name): mixed
15+
{
16+
if (isset($name[0]) && '@' == $name[0]) {
17+
if (false === $pos = strpos($name, '/')) {
18+
throw new \LogicException(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
19+
}
20+
21+
return substr($name, $pos + 1);
22+
}
23+
24+
return $name;
25+
}
26+
}

0 commit comments

Comments
 (0)