Comment intercepter des scripts déjà localisés

10

Si un plugin utilise un script (exemple important: jQuery UI Datepicker), mais que vous n'êtes pas satisfait de la façon dont le script rend la sortie, il y a deux possibilités:

1. Annulez l'enregistrement du script> Ajoutez votre propre version

Alors d' abord , vous aurez besoin de vérifier la poignée, puis trouver la priorité et le crochet ( wp_enqueue_scripts, login_enqueue_scripts, etc.) ... vous savez la perceuse.

2. Modifiez les paramètres du plugin jQuery

Normalement - si le plugin n'est pas de la merde - il pousse à travers les paramètres de PHP à JS en utilisant

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

Maintenant, c'est une façon intelligente d'ajouter vos données à un script JS, mais ... ce n'est pas filtrable par défaut. Ni WP_Scriptsni WP_Dependenciespropose aucun filtre que les utilisateurs peuvent utiliser ultérieurement

Question: Comment filtrer les arguments / paramètres qui sont déplacés de PHP vers Javascript en utilisant wp_localize_script?

kaiser
la source

Réponses:

9

wp_localize_script()appelle la méthode localize()sur la variable globale $wp_scripts. Nous pouvons définir cette variable sur une instance d'une classe enfant 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;
});

Le personnalisateur de thème n'utilise pas cela, il crée une instance distincte de WP_Scripts(voir wp-admin/customize.php). Il pourrait être possible de remplacer cela aussi:

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

Rien de tout cela n'a été testé, juste une idée.

fuxia
la source
Pourriez-vous s'il vous plaît préciser ce qu'est $ l10n? Je comprends en lui passant la poignée et l'objet, mais pas $ l10n. Merci.
Eric Leroy
1
@EricLeroy C'est le troisième paramètre de wp_localize_script(): un tableau simple ou multidimensionnel .
fuxia
Cette implémentation m'a beaucoup aidé, mais je tiens à vous avertir que cela a gâché mes scripts d'administration beaucoup de temps, ACF a cessé de fonctionner parce que les javascripts n'ont pas été imprimés en raison de la solution ci-dessus. Je n'ai pas encore de solution, mais je la cherche maintenant.
Ogier Schelvis
4

@toscho grande implémentation. Testé et vrai. Voici une version légèrement modifiée, qui passe également le $ handle et $ object_name afin que vous ne puissiez filtrer qu'en cas de besoin.

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
la source
1

La réponse acceptée est super! Mais j'ai rencontré un problème qui empêchait les champs personnalisés avancés de fonctionner dans le backend en raison d'une erreur javascript. Après avoir creusé pendant quelques heures, je suis arrivé à la conclusion que l'objet Filterable_Scripts manquait les fichiers javascript enregistrés par le plugin ACF. Je ne sais pas exactement pourquoi il a fait cela, mais j'ai trouvé une bonne solution à cela si vous rencontrez le même problème.

Le $GLOBALS['wp_scripts']heureusement encore contenait les scripts appropriés. J'ai donc fait ce qui suit dans le 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;
});

Étant donné que l'objet contient un tableau de tous les scripts enregistrés et que les poignées sont également les clés du tableau, je pourrais utiliser array_diff_key pour déterminer quels scripts manquaient dans l'objet étendu et les ajouter à nouveau. J'ai fait ça et pas seulement

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

parce que je ne voulais pas écraser les modifications apportées par l'objet étendu.

Ogier Schelvis
la source
1
J'avais une autre façon de le faire, qui était d'ajouter $acf_field_group = $GLOBALS['wp_scripts']->registered['acf-field-group'];(également acf-input) les deux balises de script acf , puis de les ajouter à nouveau à l'instance de la WP_Scriptsbalise étendue :, puis j'ai réalisé qu'ACF $GLOBALS['wp_scripts']->registered['acf-field-group'] = $acf_field_groupn'utilisait que les scripts dans Admin et je suis seulement l10ndevant donc juste enveloppé l'action et filtrer dans un !is_admintest.
MikeiLL
Bon point, en termes de performances, votre solution fonctionne mieux. J'ajoute également la vérification is_admin à ma version personnelle de ce code. La chose que j'aime toujours dans mon approche est que si les identifiants des scripts devaient changer à l'avenir ou s'il y avait de nouveaux scripts manquants dans les versions ultérieures du plugin ACF (ou d'autres plugins), je n'ai pas à changer mon code.
Ogier Schelvis
Oui, cela a aussi du sens pour moi. Je ne sais pas si tout cela est nécessaire si vous exécutez uniquement l'action sur le front-end.
MikeiLL
Hmm .. touché. Je suppose que parfois, je suis tellement pris par la recherche de la solution parfaite que j'oublie vraiment le problème initial. Cependant, si le besoin de celui-ci dans l'admin peut changer, nous avons déjà fait le calcul ;-)
Ogier Schelvis
C'est pareil ici, mon ami, mais il s'agit d'apprendre, n'est-ce pas?
MikeiLL