Pulling in var/objects/methods that could contain Latte tags

machina86
Member | 6
+
0
-

Does anyone have a solution for rendering a template that has methods that might return a {tag} in them?

Let's say you have defined the $params as
$params = [
‘business_name’ ⇒ ‘My Business’
];
$latte->render(‘page.latte’, $params);

page.latte
{$page->getSection()}

$page->getSection() returns “Welcome to {$business_name}” from a database

the initial render will of course return just that, so is a second render needed?

I'm currently working around this with
$output = $latte->renderToString(‘page.latte’, $params);
$latte->setLoader(new Latte\Loaders\StringLoader);
$latte->render($output, $latteParams);

Any suggestions or workarounds for this type of workflow?

mystik
Member | 291
+
+2
-

Are you sure you want to let users write potentially harmful latte code? It could be security hole. You would need to correctly setup latte sandbox and keep an eye for bugs.

From your example it seems you need just simple text templating. Maybe something like https://github.com/…ext-template would be better for your use case.

machina86
Member | 6
+
0
-

There are no outside users involved per se. This is more api calls that have access to our CRM and a database of reusable content. I was looking forward to being able to include components in our reusable content but when you set the loader to load by string ($latte->setLoader(new Latte\Loaders\StringLoader)) it says that any {include block from /dir/file.latte} that the “/dir/file.latte” can not be found.

I even tried to do this on first pass and get the same error.

Weird that the same {include block from /dir/file.latte} can be found when rendering from a file but not from a string.

David Grudl
Nette Core | 8142
+
+2
-

You can either modify $page->getSection() to render the content directly using $latte->renderToString(), or maybe add a filter: https://latte.nette.org/…ending-latte#…

$latte = new Latte\Engine;
$latte->addFilter('latte', fn(string $s) => new Latte\Rutime\Html($latte->renderToString($s)));

template:

{$page->getSection()|latte}
machina86
Member | 6
+
0
-

Thanks! I like the filter thing … totally makes sense. I had to go with a separate instance of the Engine though cause new Latte\Rutime\Html($latte->renderToString($s))); was expecting a file and not a string to render. So I ended up with this for now.

$latteFilter = new Latte\Engine;
$latteFilter->setLoader(new Latte\Loaders\StringLoader);
$latte->addFilter('latte', fn (string $s) => new Latte\Runtime\Html($latteFilter->renderToString($s, $params)));

Now I just need to figure out why when using $latte->setLoader(new Latte\Loaders\StringLoader) we are unable to include templates.
StringLoader says Missing template ‘/dir/templates/components.latte’ while the FileLoader has no problems loading it.

David Grudl
Nette Core | 8142
+
+1
-

It doesn't work because it uses the StringLoader again to load the second template. You'd need to create a own loader that loads the file when the path is passed in, otherwise it returns the contents of the variable.

machina86
Member | 6
+
0
-

Gotcha … the Latte\Loaders\StringLoader Class only accepts strings and cannot pull in a file. So it would expect the contents of “/dir/templates/components.latte” to be fed to it as a string not as a file. Thanks for your responses.