Cómo escapar código HTML permitiendo HTML
estoy un poco confundido sobre cómo usar la función de escape en una variable que tiene código HTML. He intentado usar esta guía https://codex.wordpress.org/Validating_Sanitizing_and_Escaping_User_Data pero no logré entenderlo. Aquí está mi código:
$output = '<p>';
$output .= '<label for="' . esc_attr( $this->get_field_id( 'title' ) ) . '">Título:</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;
Mi pregunta es ¿cómo puedo escapar $output sin perder el HTML que contiene? Lo pregunto porque estoy enviando este código a ThemeForest, donde me han rechazado varias veces por no escapar el código. Así que ahora creo que es mejor escapar estas variables, ¿correcto? ¡gracias!
Estás buscando wp_kses()
. https://developer.wordpress.org/reference/functions/wp_kses/
Hay más funciones auxiliares como wp_kses_post()
y wp_kses_data()

1. Escapado
Escapado de Atributo
<label for="<?php esc_attr( $tid ); ?>">
Escapado HTML
<label ..><?php esc_html( 'Texto' ); ?></label>
2. Traducción y Escapado
Nota:
textdomain
debe ser un slug único de tu tema/plugin.- El texto traducido debe contener un valor estático. Si tienes un valor dinámico no es necesario hacerlo listo para traducción.
1. Escapar y traducir Atributo: <label for="<?php esc_attr( $tid ); ?>">
No es necesario hacerlo listo para traducción. Si tienes un texto estático con $tid
entonces necesitas hacerlo listo para traducción, ej:
Inválido:
<label for="<?php esc_attr__( $tid, 'textdomain' ) ); ?>">
<label for="<?php printf( esc_attr__( '%s', 'textdomain' ), $tid ); ?>">
Válido:
<label for="<?php printf( esc_attr__( '%s texto estático', 'textdomain' ), $tid ); ?>">
- Escapar y traducir HTML:
<label ..><?php esc_html__( 'Texto', 'textdomain' ); ?></label>

Prueba con este método. A mí me funciona. Echo con escape HTML.
$output = '<p>';
$output .= '<label for="' . esc_attr( $this->get_field_id( 'title' ) ) . '">Título:</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 );

Tu código se ve y funciona bien para mí. El HTML en value
se conserva correctamente.
Mi única recomendación sería envolver todas tus cadenas de texto en __()
o _e()
para que puedan traducirse fácilmente. Este es un buen punto de venta en sitios de mercado como ThemeForest, ya que no todo el mundo quiere usar inglés.
$output .= '<label for="' . esc_attr( $tid ) . '">' . __( 'Título:', 'your-text-domain' ) . '</label>';
Lee más sobre I18n en el Codex de WordPress.

Si quieres hacerlo a la "manera WordPress", no almacenarías tu HTML en una variable temporal, sino que lo mostrarías directamente.
?>
<p>
<label for="<?php esc_attr_e( $this->get_field_id( 'title' ) ); ?>"> <?php _e('Título:', '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.D: También deberías internacionalizar tus cadenas de texto.
