简体   繁体   中英

Extracting variable from a twig template saved in database. Twig , PHP/Symfony

I`m working on an email template system. Scenario: In a textarea user is composing an email template, he can use text and twig so he can usee loops, condition blocks, variables etc. Then the user saves a template to the database. Before that, the template is validated form a twig structure perspective. Then we can load a template from the database (string), extract all necessary variables and as a service for it. After service returns all necessary variables I inject it into template and send an email.

For instance, the template can look like this

Hello {% if gender == 'm' %}Ms.{% else %}Mrs.{% endif% } {{name}}

Bla bla bla {{variable}} bla bla bal {{variable2}}

So basically I want to extract all variables names from a string.

I can create a twig template straight from a database by:

$template = $this->twig->createTemplate($templateFromDatabase);

I can get tokens by

$tokens = $twig->tokenize($source);

but it doesn`t tell me which tokens are variables

Finally, I can parse it and go through structure and extract variables.

$parsed = $twig->parse($tokens);

But maybe there is an easier way to get all variables names from a template. Also, do you know a way to validate twig template before saving to the database?

Also, I`m creating a service in Symfony to handle all of that and return complete email template ready to sent so I can use a PHP twig functions

Or maybe there is already bundle or something like that (i didnt find anything) Thanks in advance

Okay, the tl;dr: Use the Sandbox extension , limit the abilities of the user as much as possible. Do NOT parse the template to extract which variables are used, YOU define the variables that are available, then you provide them when it's time to render the template. Do not trust yourself to write "tests" that determine if a template is safe. (Blacklisting is flawed, closing "holes" is a never ending battle if the software is a cheese.)

Long version:

This is an opinionated answer, obviously, but I will explain: Twig allows storing variables, it allows macros, it allows loops. That means, that you can cause infinite loops, memory exhaustions and other stuff you don't want a user to be able to cause.

Now, I can totally understand where you're coming from, providing the user with the ability to customize emails via a template. But going beyond an if is crazy.

Instead, what you should do is use the sandbox extension to limit the user abilities and clearly define what is available to the user. Never the other way around. And then you just provide those variables. Not on demand or anything. Just provide them and be done with it. Any logic you might find appealing is probably flawed. This is security relevant or at least performance relevant and you should get it right.

There is a reason why almost every templating option made available to users prescribe which keywords / placeholders / constructs can be used. That reason is security and sanity. Don't be that guy that has to explain why your company "needs more servers" because the ones you have are crashing constantly or are clogged up.

If you want to verify that the template is okay: use it in the sandbox . Use a try-catch to parse the template and renders some default variables. You provide them, so that shouldn't be a problem. If an exception is thrown, pass that on to the user in a reasonable manner.

Do not allow invalid templates to hit production code. Always use the sandbox for user-provided template code. No exceptions. Do not trust the user. Ever. The user is stupid at best and outright malicious at worst. Both will cause problems.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM