Cara mencegat skrip yang sudah dilokalkan

10

Jika sebuah plugin menggunakan beberapa skrip (contoh utama: jQuery UI Datepicker), tetapi Anda tidak puas dengan cara skrip menghasilkan output, maka ada dua kemungkinan:

1. Batalkan registrasi skrip> Tambahkan versi Anda sendiri

Jadi pertama Anda akan perlu memeriksa pegangan, kemudian menemukan prioritas dan hook ( wp_enqueue_scripts, login_enqueue_scripts, dll) ... Anda tahu bor.

2. Ubah parameter plugin jQuery

Biasanya - jika plugin tersebut bukan omong kosong - itu mendorong melalui parameter dari PHP ke JS menggunakan

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

Sekarang ini adalah cara cerdas untuk menambahkan data Anda ke skrip JS, tapi ... itu tidak dapat difilter secara default. Baik WP_Scriptsatau WP_Dependenciespenawaran setiap pengguna filter yang nantinya bisa memanfaatkan

Pertanyaan: Bagaimana kita bisa memfilter argumen / parameter yang dipindahkan dari PHP ke Javascript menggunakan wp_localize_script?

kaisar
sumber

Jawaban:

9

wp_localize_script()memanggil metode localize()pada variabel global $wp_scripts. Kita dapat mengatur variabel ini ke instance dari kelas anak dari 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;
});

Penyesuai tema tidak menggunakannya, ia membuat instance terpisah dari WP_Scripts(lihat wp-admin/customize.php). Mungkin juga untuk mengganti itu:

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

Semua ini belum diuji, hanya sebuah ide.

fuxia
sumber
Bisakah Anda menentukan apa $ l10n itu? Saya mengerti menyampaikannya pegangan dan objek, tetapi tidak $ l10n. Terima kasih.
Eric Leroy
1
@EricLeroy Ini adalah parameter ketiga dari wp_localize_script(): array tunggal atau multi-dimensi .
fuxia
Implementasi ini sangat membantu saya, tetapi saya ingin memperingatkan Anda bahwa ini mengacaukan skrip admin saya, ACF berhenti bekerja karena skrip javascript tidak dicetak karena solusi di atas. Saya belum mendapatkan perbaikan, tetapi saya mencarinya sekarang.
Ogier Schelvis
4

@toscho implementasi yang bagus. Teruji dan benar. Ini adalah versi yang sedikit dimodifikasi, yang juga meneruskan $ handle dan $ object_name sehingga Anda dapat memfilter hanya saat diperlukan.

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

Jawaban yang diterima sangat bagus! Tapi saya mengalami masalah yang bidang kustom lanjutan berhenti bekerja di backend karena kesalahan javascript. Setelah menggali selama beberapa jam, saya sampai pada kesimpulan bahwa objek Filterable_Scripts hilang file javascript yang terdaftar oleh plugin ACF. Saya tidak tahu persis mengapa itu melakukan ini, tetapi saya telah menemukan solusi yang tepat untuk ini jika Anda mengalami masalah yang sama.

The $GLOBALS['wp_scripts']untungnya masih berisi script yang tepat. Jadi saya melakukan hal berikut di 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;
});

Karena objek berisi array dari semua skrip terdaftar dan pegangan juga merupakan kunci array, saya bisa menggunakan array_diff_key untuk menentukan skrip mana yang hilang dari objek yang diperluas dan menambahkannya kembali. Saya melakukan ini dan bukan hanya

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

karena saya tidak ingin menimpa perubahan yang dibuat oleh objek yang diperluas

Ogier Schelvis
sumber
1
Saya punya cara lain untuk melakukan ini, yaitu menambahkan menyimpan dua tag skrip acf $acf_field_group = $GLOBALS['wp_scripts']->registered['acf-field-group'];(juga acf-input) dan kemudian menambahkannya lagi ke contoh WP_Scriptstag yang diperluas :, $GLOBALS['wp_scripts']->registered['acf-field-group'] = $acf_field_groupkemudian menyadari bahwa ACF hanya menggunakan skrip dalam Admin dan saya hanya l10ndi depan jadi hanya membungkus aksi dan saring dalam !is_admintes.
MikeiLL
Poin bagusnya, dari segi kinerja, solusi Anda bekerja lebih baik. Saya juga menambahkan cek is_admin ke versi pribadi saya dari kode ini. Hal yang saya masih suka tentang pendekatan saya adalah bahwa jika id dari skrip berubah di masa depan atau ada skrip baru yang hilang di versi selanjutnya dari plugin ACF (atau plugin lainnya), saya tidak perlu mengubah saya kode.
Ogier Schelvis
Ya itu masuk akal bagi saya juga. Saya tidak yakin apakah itu perlu jika Anda hanya menjalankan aksinya di ujung depan.
MikeiLL
Hmm .. sentuh. Saya kira kadang-kadang saya terjebak dalam menemukan solusi yang sempurna sehingga saya lupa apa masalah sebenarnya. Namun, jika kebutuhan untuk itu di admin mungkin pernah berubah kami sudah melakukan matematika ;-)
Ogier Schelvis
Sama di sini, teman, tapi ini semua tentang belajar, bukan?
MikeiLL