Могу ли я пометить переменную Twig так же безопасно, как захваченный фрагмент текста? - PullRequest
1 голос
/ 06 февраля 2020

Вот вам Twig Fiddle . Там вы заметите этот файл включения:

{# include.twig #}

{{ text }}

И этот основной файл с несколькими попытками пометить текстовую переменную как безопасную перед ее передачей в файл включения:

{# main.twig #}

1. Pass string with HTML

{{ include('include.twig', { text: '<p>Text</p>' }) }}


2. Pass string with HTML marked safe with raw filter

{{ include('include.twig', { text: '<p>Text</p>'|raw }) }}


3. Pass variable set with string literal marked safe with raw filter

{% set text = '<p>Text</p>'|raw %}

{{ include('include.twig', { text: text }) }}


4. Pass variable set with captured chunk of text

{% set text %}<p>Text</p>{% endset %} 

{{ include('include.twig', { text: text }) }}

И Вот результаты рендеринга этого шаблона:

1. Pass string with HTML

&lt;p&gt;Text&lt;/p&gt;

2. Pass string with HTML marked safe with raw filter

&lt;p&gt;Text&lt;/p&gt;

3. Pass variable set with string literal marked safe with raw filter

&lt;p&gt;Text&lt;/p&gt;

4. Pass variable set with captured chunk of text

<p>Text</p>

Первая попытка устанавливает нежелательное поведение экранирования HTML. Стратегии 2 и 3 пытаются использовать фильтр |raw, чтобы избежать побега, но оба сбоя. Стратегия 4, использующая тег set для захвата фрагмента текста, работает отлично.

Документация для фильтра |raw гласит:

Необработанный фильтр помечает значение как «безопасное», что означает, что в среде с включенным автоматическим экранированием c эта переменная не будет экранирована, если сырой является последним фильтром, примененным к нему:

Документация для тега set гласит:

Если вы включите автоматический вывод c, Twig будет считать содержимое безопасным только при захвате фрагментов текста.

Если я что-то не упустил, это, по-видимому, два разных определения "безопасного", причем упомянутое под тегом set означает super-extra-safe .

Есть ли способ передать супер-экстра-безопасный HTML -строк, содержащий строковые литералы, в шаблон, не загрязняя мой файл уродливыми блоками захвата фрагментов set блоков?

1 Ответ

0 голосов
/ 06 февраля 2020

Ответ - нет, вы не можете, потому что twig не экранирует выражение c. Фильтр raw даже игнорируется при компиляции шаблона.

{% set hello = "<strong>Hello</strong>" %}
{% set hello = "<strong>Hello</strong>"|raw %}

Две строки выше скомпилируют в одном исходном коде

// line 1        
$context["hello"] = "<strong>Hello</strong>";
// line 2
$context["hello"] = "<strong>Hello</strong>";

source


edit:

Если вы действительно хотите это сделать, вы можете написать собственный узел include / set или добавить фильтр, который возвращает Twig\Markup

<?php
    $twig->addFilter(new \Twig\TwigFilter('safe', function($v) {
         return new \Twig\Markup($v);
    });
{% include 'text.html' with { 'text': 'Hello <strong>World</strong>'|safe, } %}

Привет Мир

...