Los peligros de wp_localize_script

26 feb. 2021
·
  • What is code
  • WordPress
·
  • JavaScript
  • php
  • wp_localize_script

Confieso que el título es un poco clickbait, la verdad, pero puede que no conozcas un problema que tiene wp_localize_script, la función que sirve para enviar datos desde PHP a JavaScript a través de un objeto global. Esto es algo que seguramente hayamos hecho alguna vez:

wp_enqueue_script( 'js-handle' );
wp_localize_script( 'js-handle', 'myGlobalObject', [ 'hey' => 'Hello World' ] );

De tal forma que cuando js-handle se haya encolado, tenemos a nuestra disposición un objeto JS en window.myGlobalObject y si accedemos a window.myGlobalObject.hey el resultado será Hello World.

Hasta aquí todo bien, es algo común en WordPress pero aquí hay otro ejemplo:

wp_enqueue_script( 'js-handle' );
wp_localize_script( 'js-handle', 'myGlobalObject', [ 'userCanPublish' => current_user_can( 'publish_posts' ) ] );

Es igual pero ahora el objeto contiene el resultado de la comprobación de permisos de usuario. ¿Qué pasará entonces en JS con este cacho?

if ( myGlobalObject.userCanPublish === false ) {
   alert( 'No tienes suficientes permisos para borrar todos los usuarios' );
}
else {
  deleteAllUsersInWordPress();
}

La función deleteAllUsersInWordPress se ejecutará siempre bajo cualquier circunstancia y esto se debe a que wp_localize_script no mantiene los tipos de datos cuando los pasa a JS. Esto pasará también con números y recordemos que en JavaScript new Boolean( '0' ) es true, con lo que hay que tener cuidado.

La solución es usar wp_add_inline_script codificando el array con wp_json_encode cuando necesitemos mantener los tipos en dicho objeto. Es un poco más feo pero bueno:

$data = wp_json_encode( [ 'userCanPublish' => false ] );
	$inline_js = <<<EOD
window.myGlobalObject = $data;
EOD;

wp_add_inline_script( 'js-handle', $inline_js, 'before' );

Ahora sí, los datos llegarán tal y como esperamos.