Los peligros de 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.