Skip to content

Commit a3a1ae9

Browse files
committed
bug #1070 [TwigComponent] Add support for namespaced templates in TemplateMap (sneakyvv)
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [TwigComponent] Add support for namespaced templates in TemplateMap | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | Tickets | | License | MIT ## Problem If a template is rendered as "_@MyNamespace/some/template.html.twig_", and it contains an embedded live component, then that name is used for the host template attribute. When obscuring this name, an error is thrown, because it cannot be found in the template map (which consists of real file paths). ## Solution Parse the name when compiling a ComponentNode, just like the FilesystemLoader would, so it becomes "_some/template.html.twig_" Commits ------- be663d1 [TwigComponent] Add support for namespaced templates in TemplateMap
2 parents ef7ddb2 + be663d1 commit a3a1ae9

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

src/LiveComponent/tests/Fixtures/Kernel.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use Symfony\UX\LiveComponent\Tests\Fixtures\Serializer\MoneyNormalizer;
3030
use Symfony\UX\TwigComponent\TwigComponentBundle;
3131
use Twig\Environment;
32+
use Twig\Loader\FilesystemLoader;
3233
use Zenstruck\Foundry\ZenstruckFoundryBundle;
3334

3435
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
@@ -52,6 +53,13 @@ public function renderTemplate(string $template, Environment $twig = null): Resp
5253
return new Response($twig->render("{$template}.html.twig"));
5354
}
5455

56+
public function renderNamespacedTemplate(string $template, Environment $twig = null): Response
57+
{
58+
$twig ??= $this->container->get('twig');
59+
60+
return new Response($twig->render('@'.FilesystemLoader::MAIN_NAMESPACE.'/'.$template.'.html.twig'));
61+
}
62+
5563
public function registerBundles(): iterable
5664
{
5765
yield new FrameworkBundle();
@@ -142,6 +150,7 @@ protected function configureRoutes(RoutingConfigurator $routes): void
142150
->prefix('/_components');
143151

144152
$routes->add('template', '/render-template/{template}')->controller('kernel::renderTemplate');
153+
$routes->add('render_namespaced_template', '/render-namespaced-template/{template}')->controller('kernel::renderNamespacedTemplate');
145154
$routes->add('homepage', '/')->controller('kernel::index');
146155
$routes->add('alternate_live_route', '/alt/{_live_component}/{_live_action}')->defaults(['_live_action' => 'get']);
147156
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,19 @@ public function testItAddsEmbeddedTemplateContextToEmbeddedComponents(): void
259259
;
260260
}
261261

262+
public function testItWorksWithNamespacedTemplateNamesForEmbeddedComponents(): void
263+
{
264+
$templateName = 'render_embedded_with_blocks.html.twig';
265+
$obscuredName = 'fb7992f74bbb43c08e47b7cf5c880edb';
266+
$this->addTemplateMap($obscuredName, $templateName);
267+
268+
$this->browser()
269+
->visit('/render-namespaced-template/render_embedded_with_blocks')
270+
->assertSuccessful()
271+
->assertElementAttributeContains('.component2', 'data-live-props-value', '"data-host-template":"'.$obscuredName.'"')
272+
;
273+
}
274+
262275
public function testItUseBlocksFromEmbeddedContextUsingMultipleComponents(): void
263276
{
264277
$templateName = 'render_multiple_embedded_with_blocks.html.twig';

src/TwigComponent/src/Twig/ComponentNode.php

Lines changed: 17 additions & 1 deletion
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->getAttribute('name'))
71+
->string($this->parseTemplateName($this->getAttribute('name')))
7272
->raw(', ')
7373
->raw($this->getAttribute('index'))
7474
->raw(");\n")
@@ -91,4 +91,20 @@ 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+
}
94110
}

0 commit comments

Comments
 (0)