Mengabaikan fungsi dalam kelas plugin

8

Saya memperbarui salah satu plugin saya dan saya sedikit macet dengan fungsi yang sudah usang.

Awalnya, plugin saya memiliki variabel global dan kelas utama plugin adalah instantiated dan disimpan dalam variabel global. Dengan cara ini pengguna dapat menggunakan fungsi global untuk mengakses di kelas plugin.

$GLOBALS['my_custom_plugin'] = new my_custom_plugin();

Kemudian, misalnya, dalam FAQ saya, saya memiliki kode yang menunjukkan cara menghapus salah satu fungsi kelas saya dari hook tertentu dan menambahkan ke hook yang berbeda:

function move_input(){ 
    global $my_custom_plugin;
    remove_action( 'before_main_content', array( $my_custom_plugin, 'display_input') );
    add_action( 'after_main_content', array( $my_custom_plugin, 'display_input' ) );
}
add_action( 'wp_head' , 'move_input' );

Sekarang, dalam pembaruan saya display_input()fungsi telah dipindahkan ke kelas lain dan saya ingin memberi tahu orang-orang bagaimana cara mengaksesnya. Saya mencoba mengganti fungsi asli (di kelas plugin utama) dengan pemberitahuan penghentian berikut:

public function display_input() { 
    _deprecated_function( 'display_price', '2.0', 'my_custom_plugin()->display->display_input' );
    return $this->display->display_input();
}

Namun, fungsi add_actiondan remove_actionsepertinya tidak memicu pemberitahuan penghentian. Anehnya, menghapus fungsi sepenuhnya tidak menyebabkan kesalahan baik meskipun array( $my_custom_plugin, 'display_input')tidak ada.

Jika seseorang mencoba mengakses fungsi secara langsung:

$my_custom_plugin->display_input();

Lalu saya melihat pemberitahuan debug. Apakah ini hasil yang diharapkan _deprecated_function()? atau aku melewatkan sesuatu? Apakah mungkin untuk menampilkan pemberitahuan debug ketika seseorang mencoba untuk menghapus atau menambahkan tindakan menggunakan fungsi yang sudah usang?

Memperbarui

Saya menyadari bahwa saya tidak melihat pesan debug add_actionkarena saya menambahkannya cukup rendah pada halaman. #Telapak tangan! Namun, saya masih belum melihat pemberitahuan debug untuk remove_action.

helgatheviking
sumber
call_user_func(function(){trigger_error('hello?');});Pekerjaan yang menarik , tetapi gagal dalam panggilan balik yang terdaftar per add_action.
fuxia
Mempersiapkan wajah, tetapi apakah itu pertanyaan atau pernyataan?
Helgatheviking
Hanya hasil tes. Saya juga terkejut.
fuxia
Ok, jadi aku tidak benar-benar diabaikan apa-apa, itu hanya bagaimana itu adalah ?
Helgatheviking
2
Oh, Monitor Kueri telah menyembunyikan pesan di pengaturan saya. Pesan untuk add_action()sebenarnya ada di sana. remove_action()tidak bisa ditangani seperti itu.
fuxia

Jawaban:

2

Callback tidak ada

Salah satu hal yang menyenangkan adalah, bahwa keduanya do_action(), tidak juga apply_filters()memicu kesalahan jika panggilan balik tidak ada. Ini berarti bahwa ini adalah cara paling aman untuk memasukkan data plugin ke dalam template: Jika sebuah plugin dimatikan dan do_action()/ apply_filters()tidak menemukan panggilan balik dalam $wp_filtersarray global , tidak ada yang terjadi.

Output Kesalahan

Sekarang ketika Anda memanggil remove_filter()fungsi / metode yang awalnya mengaitkan callback, callback hanya akan dihapus dari array global, yang berarti bahwa callback tidak akan pernah dieksekusi karena sudah tidak terdaftar lagi.

Solusinya sederhana: Hapus panggilan balik setelah dipicu, dengan menghapusnya dari dalam panggilan balik itu sendiri.

Menghapus Panggilan Balik

Kita semua tahu bahwa plugin WPs "API" adalah masalah ketika harus menghapus. Masalahnya terutama adalah konstruksi aneh untuk menambahkan nama "unik" ke kunci dalam global $wp_filter;array. Solusi yang sangat sederhana adalah dengan hanya menggunakan __METHOD__dan memanggil filter yang ingin Anda hapus dalam konteks statis:

class FOoooo
{
    public function __construct()
    {
        add_filter( 'hook', array( __CLASS__, 'bar' ) );
    }
    public static function bar( $baz )
    {
        remove_filter( current_filter(), __METHOD__ );

        return $baz;
    }
}

Meskipun ini tidak baik, itu ... semacam solusi untuk beberapa kasus penggunaan. Tetapi bahkan jangan berpikir untuk menghapus penutupan.

Di atas hanya menghapus callback, masih menjalankannya. Anda masih bisa melangkah lebih jauh dan menggunakan remove_all_actions()(atau remove_all_filters()).

// Check if a callback is attached and tell about the deprecated stuff
if ( has_action( 'before_main_content' ) )
    _deprecated_function( 'display_price', '2.0', 'my_custom_plugin()->display->display_input' );
// Remove the callback
remove_all_actions( 'before_main_content' );

Anda mungkin bahkan bisa melangkah lebih jauh, mengekstrak panggilan balik dari array filter global dan melampirkannya kembali ke hook / filter baru (jika mereka kompatibel).

kaisar
sumber
Terima kasih Kaiser! Ini adalah jawaban yang luar biasa dan terperinci. Saya akan mencoba mengujinya besok.
Helgatheviking