Cómo interceptar guiones ya localizados

10

Si un complemento utiliza algún script (ejemplo destacado: jQuery UI Datepicker), pero no está satisfecho con la forma en que el script representa la salida, entonces hay dos posibilidades:

1. Anule el registro del script> Agregue su propia versión

Así que primero que había necesidad de comprobar el mango, y luego encontrar la prioridad y el gancho ( wp_enqueue_scripts, login_enqueue_scripts, etc.) ... Lo de siempre.

2. Cambie los parámetros del complemento jQuery

Normalmente, si el complemento no es basura, pasa a través de los parámetros de PHP a JS usando

wp_localize_script( $handle, $object_name, array( 
    // data
) );

Ahora, esta es una forma inteligente de agregar sus datos a un script JS, pero ... no se puede filtrar de manera predeterminada. Ni WP_Scriptstampoco WP_Dependenciesofrece ningún filtro que los usuarios puedan utilizar más tarde

Pregunta: ¿Cómo podemos filtrar los argumentos / parámetros que se mueven de PHP a Javascript usando wp_localize_script?

emperador
fuente

Respuestas:

9

wp_localize_script()llama al método localize()en la variable global $wp_scripts. Podemos establecer esta variable en una instancia de una clase secundaria de WP_Scripts:

class Filterable_Scripts extends WP_Scripts
{
    function localize( $handle, $object_name, $l10n )
    {
        $l10n = apply_filters( 'script_l10n', $l10n, $handle, $object_name );
        return parent::localize($handle, $object_name, $l10n);
    }
}

add_action( 'wp_loaded', function() {
    $GLOBALS['wp_scripts'] = new Filterable_Scripts;
});

El personalizador de temas no usa eso, crea una instancia separada de WP_Scripts(ver wp-admin/customize.php). Podría ser posible reemplazar eso también:

add_action( 'customize_controls_init', function() {
    $GLOBALS['wp_scripts'] = new Filterable_Scripts;
    $GLOBALS['wp_scripts']->registered = $GLOBALS['registered'];
});

Nada de esto ha sido probado, solo una idea.

fuxia
fuente
¿Podría especificar qué es $ l10n? Entiendo pasarle el identificador y el objeto, pero no $ l10n. Gracias.
Eric Leroy
1
@EricLeroy Es el tercer parámetro de wp_localize_script(): una matriz única o multidimensional .
fuxia
Esta implementación me ayudó mucho, pero quiero advertirle que estropeó mis scripts de administrador a lo grande, ACF dejó de funcionar porque los javascripts no se imprimieron debido a la solución anterior. Todavía no tengo una solución, pero la estoy buscando ahora.
Ogier Schelvis el
4

@toscho gran implementación. Probado y verdadero. Aquí hay una versión ligeramente modificada, que también pasa el $ handle y $ object_name para que pueda filtrar solo cuando sea necesario.

class Filterable_Scripts extends WP_Scripts
{
    function localize( $handle, $object_name, $l10n )
    {
        $l10n = apply_filters( 'script_l10n', $l10n, $handle, $object_name );
        return parent::localize($handle, $object_name, $l10n);
    }
}

add_action( 'init', function() {
    $GLOBALS['wp_scripts'] = new Filterable_Scripts;
});

add_filter('script_l10n', 'se108362_example_filter', 10 , 3);

// Example
function se108362_example_filter($l10n, $handle, $object_name ) {
    if('js-handle' == $handle && 'jsVariable' == $object_name) {
       return 'Something Else';
    }
    return $l10n;
}
Eric Holmes
fuente
1

¡La respuesta aceptada es genial! Pero me encontré con un problema que Advanced Custom Fields dejó de funcionar en el back-end debido a un error de JavaScript. Después de excavar durante unas horas, llegué a la conclusión de que al objeto Filterable_Scripts le faltaban los archivos javascript registrados por el complemento ACF. No sé exactamente por qué hizo esto, pero he encontrado una solución adecuada para esto si te encuentras con el mismo problema.

La $GLOBALS['wp_scripts']afortunadamente, aún contenían las secuencias de comandos adecuados. Entonces hice lo siguiente en add_action:

add_action( 'wp_loaded', function() {
    $fscripts = new Filterable_Scripts();

    $missing_scripts = array_diff_key( $GLOBALS['wp_scripts']->registered, $fscripts->registered);
    foreach($missing_scripts as $mscript){
        $fscripts->registered[$mscript->handle] = $mscript;
    }

    $GLOBALS['wp_scripts'] = $fscripts;
});

Debido a que el objeto contiene una matriz de todos los scripts registrados y los controladores también son las claves de la matriz, podría usar array_diff_key para determinar qué scripts faltaban en el objeto extendido y volver a agregarlos. Hice esto y no solo

$fscripts->registered = $GLOBALS['wp_scripts']->registered;

porque no quería sobrescribir ningún cambio realizado por el objeto extendido.

Ogier Schelvis
fuente
1
Tenía otra forma de hacer esto, que era agregar guardar las dos etiquetas de script acf $acf_field_group = $GLOBALS['wp_scripts']->registered['acf-field-group'];(también acf-input) y luego agregarlas nuevamente a la instancia de la WP_Scriptsetiqueta extendida : $GLOBALS['wp_scripts']->registered['acf-field-group'] = $acf_field_groupluego me di cuenta de que ACF solo está usando los scripts dentro de Admin y estoy solo l10nen frente, así que simplemente envolvió la acción y filtró en una !is_adminprueba.
MikeiLL
Buen punto, en cuanto al rendimiento, su solución funciona mejor. También estoy agregando el cheque is_admin a mi versión personal de este código. Lo que aún me gusta de mi enfoque es que si las identificaciones de los scripts cambian en el futuro o faltan nuevos scripts en versiones posteriores del complemento ACF (u otros complementos), no tengo que cambiar mi código.
Ogier Schelvis
Sí, eso también tiene sentido para mí. No estoy seguro de si es necesario si solo está ejecutando la acción en el front-end.
MikeiLL
Hmm .. touché. Supongo que a veces me encuentro atrapado tanto en encontrar la solución perfecta que olvido de qué se trataba realmente el problema inicial. Sin embargo, si la necesidad en el administrador pudiera cambiar, ya hicimos los cálculos ;-)
Ogier Schelvis
Lo mismo aquí, amigo, pero se trata de aprender, ¿no?
MikeiLL