So fangen Sie bereits lokalisierte Skripte ab

10

Wenn ein Plugin ein Skript verwendet (prominentes Beispiel: jQuery UI Datepicker), Sie jedoch nicht zufrieden sind, wie das Skript die Ausgabe rendert, gibt es zwei Möglichkeiten:

1. Heben Sie die Registrierung des Skripts auf.> Fügen Sie Ihre eigene Version hinzu

Also zuerst müssen Sie den Griff überprüfen, dann finden die Priorität und der Haken ( wp_enqueue_scripts, login_enqueue_scriptsusw.) ... Sie die Bohrer wissen.

2. Ändern Sie die Parameter des jQuery-Plugins

Normalerweise - wenn das Plugin kein Mist ist - werden die Parameter von PHP nach JS mit übertragen

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

Dies ist eine clevere Möglichkeit, Ihre Daten zu einem JS-Skript hinzuzufügen, aber ... sie können standardmäßig nicht gefiltert werden. Weder WP_Scriptsnoch WP_DependenciesAngebote irgendwelche Filter können Benutzer später nutzen

Frage: Wie können wir die Argumente / Parameter filtern, die von PHP nach Javascript verschoben werden wp_localize_script?

Kaiser
quelle

Antworten:

9

wp_localize_script()Ruft die Methode localize()für die globale Variable auf $wp_scripts. Wir können diese Variable auf eine Instanz einer untergeordneten Klasse setzen von 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;
});

Der Theme-Customizer verwendet dies nicht, sondern erstellt eine separate Instanz von WP_Scripts(siehe wp-admin/customize.php). Möglicherweise kann dies auch ersetzt werden:

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

Nichts davon wurde getestet, nur eine Idee.

Fuxia
quelle
Könnten Sie bitte angeben, was $ l10n ist? Ich verstehe, dass ich ihm den Handle und das Objekt übergebe, aber nicht $ l10n. Vielen Dank.
Eric Leroy
1
@EricLeroy Dies ist der dritte Parameter von wp_localize_script(): einem ein- oder mehrdimensionalen Array .
Fuxia
Diese Implementierung hat mir sehr geholfen, aber ich möchte Sie warnen, dass sie meine Administrationsskripte stark durcheinander gebracht hat. ACF hat aufgehört zu arbeiten, weil die Javaskripte aufgrund der oben genannten Lösung nicht gedruckt wurden. Ich habe noch keine Lösung, aber ich suche jetzt danach.
Ogier Schelvis
3

@toscho tolle Implementierung. Getestet und wahr. Hier ist eine leicht modifizierte Version, die auch das $ handle und $ object_name übergibt, sodass Sie nur bei Bedarf filtern können.

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
quelle
1

Die akzeptierte Antwort ist großartig! Ich bin jedoch auf ein Problem gestoßen, bei dem Advanced Custom Fields aufgrund eines Javascript-Fehlers im Backend nicht mehr funktioniert. Nachdem ich einige Stunden lang gegraben hatte, kam ich zu dem Schluss, dass dem Filterable_Scripts-Objekt die vom ACF-Plugin registrierten Javascript-Dateien fehlten. Ich weiß nicht genau, warum das so war, aber ich habe eine richtige Lösung dafür gefunden, wenn Sie auf dasselbe Problem stoßen.

Das $GLOBALS['wp_scripts']enthielt zum Glück noch die richtigen Skripte. Also habe ich folgendes gemacht in 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;
});

Da das Objekt ein Array aller registrierten Skripte enthält und die Handles auch die Array-Schlüssel sind, könnte ich array_diff_key verwenden, um festzustellen, welche Skripte im erweiterten Objekt fehlten, und sie erneut hinzufügen. Ich habe das getan und nicht nur

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

weil ich keine vom erweiterten Objekt vorgenommenen Änderungen überschreiben wollte.

Ogier Schelvis
quelle
1
Ich hatte eine andere Möglichkeit, dies zu tun, nämlich die beiden acf-Skript-Tags $acf_field_group = $GLOBALS['wp_scripts']->registered['acf-field-group'];(auch acf-input) zu speichern und sie dann erneut zur Instanz des erweiterten WP_ScriptsTags hinzuzufügen : $GLOBALS['wp_scripts']->registered['acf-field-group'] = $acf_field_groupDann wurde mir klar, dass ACF nur die Skripte in Admin verwendet und ich bin nur l10nvorne also einfach die Aktion einwickeln und in einem !is_adminTest filtern .
MikeiLL
Guter Punkt, in Bezug auf die Leistung funktioniert Ihre Lösung besser. Ich füge auch den is_admin-Check zu meiner persönlichen Version dieses Codes hinzu. Das, was ich an meinem Ansatz immer noch mag, ist, dass ich meine nicht ändern muss, wenn sich die IDs der Skripte in Zukunft ändern sollten oder wenn in späteren Versionen des ACF-Plugins (oder anderer Plugins) neue Skripte fehlen Code.
Ogier Schelvis
Ja, das macht auch für mich Sinn. Ich bin mir nicht sicher, ob etwas davon notwendig ist, wenn Sie die Aktion nur am Frontend ausführen.
MikeiLL
Hmm .. touché. Ich denke, manchmal bin ich so sehr damit beschäftigt, die perfekte Lösung zu finden, dass ich vergesse, worum es bei dem anfänglichen Problem wirklich ging. Sollte sich die Notwendigkeit im Admin jedoch jemals ändern, haben wir bereits nachgerechnet ;-)
Ogier Schelvis
Das gleiche hier, Freund, aber es geht nur ums Lernen, nicht wahr?
MikeiLL