Skip to content

Commit

Permalink
bug #1070 [TwigComponent] Add support for namespaced templates in Tem…
Browse files Browse the repository at this point in the history
…plateMap (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
  • Loading branch information
weaverryan committed Aug 24, 2023
2 parents ef7ddb2 + be663d1 commit a3a1ae9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
9 changes: 9 additions & 0 deletions src/LiveComponent/tests/Fixtures/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use Symfony\UX\LiveComponent\Tests\Fixtures\Serializer\MoneyNormalizer;
use Symfony\UX\TwigComponent\TwigComponentBundle;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use Zenstruck\Foundry\ZenstruckFoundryBundle;

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

public function renderNamespacedTemplate(string $template, Environment $twig = null): Response
{
$twig ??= $this->container->get('twig');

return new Response($twig->render('@'.FilesystemLoader::MAIN_NAMESPACE.'/'.$template.'.html.twig'));
}

public function registerBundles(): iterable
{
yield new FrameworkBundle();
Expand Down Expand Up @@ -142,6 +150,7 @@ protected function configureRoutes(RoutingConfigurator $routes): void
->prefix('/_components');

$routes->add('template', '/render-template/{template}')->controller('kernel::renderTemplate');
$routes->add('render_namespaced_template', '/render-namespaced-template/{template}')->controller('kernel::renderNamespacedTemplate');
$routes->add('homepage', '/')->controller('kernel::index');
$routes->add('alternate_live_route', '/alt/{_live_component}/{_live_action}')->defaults(['_live_action' => 'get']);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,19 @@ public function testItAddsEmbeddedTemplateContextToEmbeddedComponents(): void
;
}

public function testItWorksWithNamespacedTemplateNamesForEmbeddedComponents(): void
{
$templateName = 'render_embedded_with_blocks.html.twig';
$obscuredName = 'fb7992f74bbb43c08e47b7cf5c880edb';
$this->addTemplateMap($obscuredName, $templateName);

$this->browser()
->visit('/render-namespaced-template/render_embedded_with_blocks')
->assertSuccessful()
->assertElementAttributeContains('.component2', 'data-live-props-value', '"data-host-template":"'.$obscuredName.'"')
;
}

public function testItUseBlocksFromEmbeddedContextUsingMultipleComponents(): void
{
$templateName = 'render_multiple_embedded_with_blocks.html.twig';
Expand Down
18 changes: 17 additions & 1 deletion src/TwigComponent/src/Twig/ComponentNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function compile(Compiler $compiler): void
->raw('), ')
->raw($this->getAttribute('only') ? '[]' : '$context')
->raw(', ')
->string($this->getAttribute('name'))
->string($this->parseTemplateName($this->getAttribute('name')))
->raw(', ')
->raw($this->getAttribute('index'))
->raw(");\n")
Expand All @@ -91,4 +91,20 @@ public function compile(Compiler $compiler): void
->raw("\n")
;
}

/**
* Copied from Twig\Loader\FilesystemLoader, and adjusted to needs for this class.
*/
private function parseTemplateName(string $name): mixed
{
if (isset($name[0]) && '@' == $name[0]) {
if (false === $pos = strpos($name, '/')) {
throw new \LogicException(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
}

return substr($name, $pos + 1);
}

return $name;
}
}

0 comments on commit a3a1ae9

Please sign in to comment.