web-dev-qa-db-fra.com

Commentaire intercepter des scripts déjà localisés

Si un plugin utilise un script (exemple évident: jQuery UI Datepicker), mais que vous n'êtes pas satisfait de la manière dont le script restitue la sortie, il existe alors deux possibilités:

1. Annuler l'enregistrement du script> Ajouter votre propre version

Donc, vous devez d’abord vérifier la poignée, puis trouver la priorité et le crochet (wp_enqueue_scripts, login_enqueue_scripts, etc.) ... vous connaissez l’exercice.

2. Changer les paramètres du plugin jQuery

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

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

Maintenant, c’est un moyen astucieux d’ajouter vos données à un script JS, mais ... ce n’est pas filtrable par défaut. Ni WP_Scripts ni WP_Dependencies n'offre aucun des utilisateurs du filtre ne peut utiliser plus tard

Question: Comment pouvons-nous filtrer les arguments/paramètres qui sont déplacés de PHP vers Javascript à l'aide de wp_localize_script?

8
kaiser

wp_localize_script() appelle la méthode localize() sur la variable globale $wp_scripts. Nous pouvons définir cette variable sur une instance de child class of 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 ne l'utilise pas, 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.

8
fuxia

@toscho grande implémentation. Testé et vrai. Voici une version légèrement modifiée, qui transmet également les noms $ handle et $ object_name afin que vous puissiez filtrer uniquement lorsque cela est nécessaire.

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;
}
2
Eric Holmes

La réponse acceptée est super! Mais j’ai rencontré un problème en raison du fait que Advanced Custom Fields ne fonctionnait plus dans le backend à cause d’une erreur javascript. Après avoir creusé pendant quelques heures, je suis parvenu à la conclusion que l’objet Filterable_Scripts manquait des fichiers javascript enregistrés par le plugin ACF. Je ne sais pas exactement pourquoi il a agi de la sorte, mais j’ai trouvé une solution appropriée si vous rencontrez le même problème.

Heureusement, le $GLOBALS['wp_scripts'] contenait toujours 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 descripteurs sont également les clés du tableau, je pourrais utiliser array_diff_key pour déterminer les scripts manquants dans l'objet étendu et les rajouter. Je l'ai fait et pas seulement

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

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

1
Ogier Schelvis