Twig icon indicating copy to clipboard operation
Twig copied to clipboard

EscaperRuntime::setSafeClasses() implementation

Open joeworkman opened this issue 1 year ago • 2 comments

My Twig extension implements a global that is an adapter for my CMS.

public function getGlobals(): array
{
    return [
            'cms' => $this->adapter,
    ];
}

I would like to set all functions for this class to be safe. I thought that I could use EscaperRuntime::setSafeClasses() for this.

$this->twig->getRuntime(EscaperRuntime::class)->setSafeClasses([
	TotalForm::class           => ['html'],
	TotalCMSTwigAdapter::class => ['html'],
]);

It's not working. Am I close?

joeworkman avatar Jun 28 '24 19:06 joeworkman

Can you tell us more about what does not work? I've just tried and it works well. I realize that setSafeClasses() might be a confusing method name. This is only to avoid escaping the return value for __toString() methods.

fabpot avatar Jun 30 '24 07:06 fabpot

Let me explain what I am trying to accomplish. The TotalForm class is essentially a form builder for my CMS. Its still a work in progress, but the twig currently looks like this...

{% set form  = cms.objectFormBuilder('blog', {}) %}

{{ form.addField('text', 'mytext', {}) }}
{{ form.build() }}

The problem that I was trying to overcome was the need to add | raw to the build statement since it outputs HTML. I thought setting the TotalForm class (the form variable is an instance of TotalForm) to be "safe" would fix that.

joeworkman avatar Jul 01 '24 00:07 joeworkman

What you are displaying is not the form variable but the output of form.build()

stof avatar Sep 03 '24 10:09 stof

Yes. That is correct. For now, I have globally disabled the need to use raw. Not ideal but I have to admit that it's nice since so much of my implementation displays HTML from my CMS.

joeworkman avatar Sep 03 '24 13:09 joeworkman

Make your build method return a stringable object from a class configured as safe class (which could be the \Twig\Markup object).

When you return a string, you have no way to mark it as safe.

An alternative method is to create a Twig function that would do this build (as Twig functions can tell Twig whether they output a safe value or no), making it look like {{ render_form(form) }}

stof avatar Sep 03 '24 14:09 stof

I'm closing this issue as it was based on a misunderstanding of what safe classes are about. The phpdoc type of the method has been improved to make it more likely for such mistake to be detected.

stof avatar Oct 02 '24 09:10 stof