Как экранировать HTML-код с разрешенным HTML
Я немного запутался в том, как использовать функцию экранирования для переменной, содержащей HTML-код. Я пытался разобраться с этим используя https://codex.wordpress.org/Validating_Sanitizing_and_Escaping_User_Data, но не смог понять как это сделать правильно. Вот мой код:
$output = '<p>';
$output .= '<label for="' . esc_attr( $this->get_field_id( 'title' ) ) . '">Заголовок:</label>';
$output .= '<input type="text" class="widefat" id="' . esc_attr( $this->get_field_id( 'title' ) ) . '" name="' . esc_attr( $this->get_field_name( 'title' ) ) . '" value="' . esc_attr( $title ) . '"';
$output .= '</p>';
echo $output;
Мой вопрос в том, как я могу экранировать $output без потери HTML-разметки? Я спрашиваю, потому что отправляю этот код на ThemeForest. Оттуда мне несколько раз отклоняли код из-за отсутствия экранирования. Поэтому теперь я думаю, что лучше экранировать эти переменные, верно? Спасибо!

Вам нужна функция wp_kses()
. https://developer.wordpress.org/reference/functions/wp_kses/
Также существуют вспомогательные функции, такие как wp_kses_post()
и wp_kses_data()

1. Экранирование
Экранирование атрибута
<label for="<?php esc_attr( $tid ); ?>">
Экранирование HTML
<label ..><?php esc_html( 'Текст' ); ?></label>
2. Перевод и экранирование
Примечание:
textdomain
должен быть уникальным слагом вашей темы/плагина.- Переводимая строка должна содержать статичное значение. Если у вас динамическое значение, то его не нужно делать готовым для перевода.
1. Экранирование и перевод атрибута: <label for="<?php esc_attr( $tid ); ?>">
Не нужно делать это готовым для перевода. Если у вас есть статичная строка с $tid
, тогда её нужно сделать готовой для перевода, например:
Неправильно:
<label for="<?php esc_attr__( $tid, 'textdomain' ) ); ?>">
<label for="<?php printf( esc_attr__( '%s', 'textdomain' ), $tid ); ?>">
Правильно:
<label for="<?php printf( esc_attr__( '%s статичный текст', 'textdomain' ), $tid ); ?>">
- Экранирование и перевод HTML:
<label ..><?php esc_html__( 'Текст', 'textdomain' ); ?></label>

Попробуйте этот метод. Он работает у меня. Экранирование вывода с помощью HTML.
$output = '<p>';
$output .= '<label for="' . esc_attr( $this->get_field_id( 'title' ) ) . '">Заголовок:</label>';
$output .= '<input type="text" class="widefat" id="' . esc_attr( $this->get_field_id( 'title' ) ) . '" name="' . esc_attr( $this->get_field_name( 'title' ) ) . '" value="' . esc_attr( $title ) . '"';
$output .= '</p>';
$allowed_html = array(
'input' => array(
'type' => array(),
'id' => array(),
'name' => array(),
'value' => array(),
),
);
echo wp_kses($output ,$allowed_html );

Ваш код выглядит и работает хорошо на мой взгляд. HTML в value
сохраняется.
Моя единственная рекомендация — обернуть все текстовые строки в __()
или _e()
, чтобы их можно было легко переводить. Это хорошее преимущество для продажи на площадках вроде ThemeForest, так как не все хотят использовать английский язык.
$output .= '<label for="' . esc_attr( $tid ) . '">' . __( 'Заголовок:', 'your-text-domain' ) . '</label>';
Узнайте больше про интернационализацию (I18n) в Кодексе WordPress.

Если вы хотите сделать это "по-вордпрессовски", вам не следует сохранять HTML во временной переменной, а выводить его напрямую.
?>
<p>
<label for="<?php esc_attr_e( $this->get_field_id( 'title' ) ); ?>"> <?php _e('Заголовок:', 'tex-domain'); ?></label>
<input type="text" class="widefat" id="<?php esc_attr_e( $this->get_field_id( 'title' ) ); ?>" value="<?php esc_attr_e( $title ); ?>" />
</p>
<?php
P.S: Также вам следует интернационализировать ваши текстовые строки.
