Bagaimana cara saya mengganti fungsi, yang dideklarasikan di dalam kelas plugin, di functions.php?

9

Saya ingin memodifikasi fungsi dalam sebuah plugin. Ini dinyatakan dalam file utama plugin seperti ini:

class WCPGSK_Main {
  ...
  public function wcpgsk_email_after_order_table($order) {
    ...
  }
}

Tambahkan dipanggil dari sana seperti ini:

add_action( 'woocommerce_email_after_order_table', array($this, 'wcpgsk_email_after_order_table') );

Saya kira akan mungkin untuk menggantinya jika memiliki akses ke kelas di functions.php. Maka saya akan dapat menulis sesuatu seperti ini:

$wcpgsk = new WCPGSK_Main;

remove_action( 'woocommerce_email_after_order_table', array($wcpgsk, 'wcpgsk_email_after_order_table') );

function customized_wcpgsk_email_after_order_table($order) {
  ...
}
add_action( 'woocommerce_email_after_order_table', array($wcpgsk, 'customized_wcpgsk_email_after_order_table') );

Pemikiran saya untuk mendapatkan akses ke kelas dalam file functions.php adalah untuk memasukkan file di mana kelas dideklarasikan dalam functions.php:

require_once('/wp-content/plugins/woocommerce-poor-guys-swiss-knife/woocommerce-poor-guys-swiss-knife.php');
$wcpgsk = new WCPGSK_Main;
...

Tapi ini tidak berfungsi karena file plugin dimasukkan ketika plugin diinisialisasi di WordPress, saya kira.

Apakah ada cara untuk menulis ulang fungsi tanpa menyentuh file plugin?

Igor Skoldin
sumber

Jawaban:

8

Ini seharusnya bekerja:

add_action( 'woocommerce_init', 'remove_wcpgsk_email_order_table' );
function remove_wcpgsk_email_order_table() {

    global $wcpgsk;
    remove_action( 'woocommerce_email_after_order_table', array( $wcpgsk, 'wcpgsk_email_after_order_table' ) );

}
passatgt
sumber
1
ada fungsi remove_action: codex.wordpress.org/Function_Reference/remove_action
Alex Older
Ya, itu yang saya lewatkan, plugin ini memiliki variabel yang dapat diakses sebagai variabel global. Kebodohan saya. Terima kasih atas jawaban Anda, ini berfungsi dalam kasus khusus ini (untuk plugin ini).
Igor Skoldin
Alex Older menautkan ke tempat yang menjelaskan mengapa jawabannya bekerja. Remove_action menerima larik dengan kelas statis atau instance tempat Anda ingin menghapus metode.
ninja08
11

Jika plugin Anda terdaftar seperti ini:

class Test_Class_Parent {
  function __construct() {
    add_action('wp_head',array($this,'test_method'));
  }

  function test_method() {
    echo 'Echoed from the parent';
  }
}
$p = new Test_Class_Parent();

Maka Anda harus dapat menghapus filter dengan mengakses global:

class Test_Class_Child extends Test_Class_Parent {
  function __construct() {
    $this->unregister_parent_hook();
    add_action('wp_head',array($this,'test_method'));
  }

  function unregister_parent_hook() {
    global $p;
    remove_action('wp_head',array($p,'test_method'));
  }

  function test_method() {
    echo 'Echoed from the child';
  }
}
$c = new Test_Class_Child();

Jika tidak, Anda harus merangkak $wp_filter globaluntuk kunci pendaftaran:

class Test_Class_Child extends Test_Class_Parent {
  function __construct() {
    $this->unregister_parent_hook();
    add_action('wp_head',array($this,'test_method'));
  }

  function unregister_parent_hook() {
    global $wp_filter;
    if (!empty($wp_filter['wp_head'])) {
      foreach($wp_filter['wp_head'] as $cb) {
        foreach ($cb as $k => $v) {
          if (
            isset($v['function'])
            && is_a($v['function'][0],'Test_Class_Parent')
            && isset($v['function'][1])
            && 'test_method' == $v['function'][1]
          ) {
            remove_action('wp_head',$k);
          }
        }
      }
    }
  }

  function test_method() {
    echo 'Echoed from the child';
  }
}
$c = new Test_Class_Child();

Ini adalah sumber daya yang intensif dan harus benar-benar tidak dilakukan kecuali Anda tidak punya pilihan lain.

s_ha_dum
sumber
2
Ini harus menjadi jawaban yang diterima. Ini lebih bermanfaat secara umum, dan tidak terbatas pada kasus khusus OP saja.
David R.
1

Plugin itu membuat fungsi wcpgsk_init()initnya dapat digunakan, jadi cara lain untuk menimpanya adalah dengan mendefinisikannya terlebih dahulu di plugin yang harus digunakan (karena sudah terlambat di "fungsi.php" tema Anda). Jadi Anda bisa meletakkan override Anda di "wp-content / mu-plugins / functions.php":

function wcpgsk_init() {
    global $wcpgsk, $wcpgsk_about, $wcpgsk_options, $wcpgsk_session, $wcpgsk_woocommerce_active;    
    //only continue loading
    if ( $wcpgsk_woocommerce_active && version_compare( WOOCOMMERCE_VERSION, "2.0" ) >= 0 ) {
        $FILE = WP_PLUGIN_DIR . '/woocommerce-poor-guys-swiss-knife/woocommerce-poor-guys-swiss-knife.php'; // Fake __FILE__
        $dirname = dirname( $FILE ) . '/';
        $wcpgsk_options = get_option('wcpgsk_settings', true);
        require_once( $dirname . 'classes/woocommerce-poor-guys-swiss-knife.php' );
        require_once( $dirname . 'classes/woocommerce-poor-guys-swiss-knife-about.php' );   
        require_once( $dirname . 'wcpgsk-af.php' );

        if ( !is_admin() ) :
            add_action( 'plugins_loaded', 'wcpgsk_load_wcsession_helper' );
        endif;

        // Your override.
        class My_WCPGSK_Main extends WCPGSK_Main {
            public function wcpgsk_email_after_order_table($order) {
                echo "O la la";
            }
        }
        define( 'WCRGSK_DOMAIN', WCPGSK_DOMAIN ); // Fix typo! (WooCommerce Rich Guys Swiss Knife?)

        //load into our global
        $wcpgsk = new My_WCPGSK_Main( $FILE );
        $wcpgsk->version = '2.2.4'; 
        $wcpgsk->wcpgsk_hook_woocommerce_filters();


    } elseif ( version_compare( WOOCOMMERCE_VERSION, "2.0" ) < 0 ) {
        add_action( 'admin_notices', 'wcpgsk_woocommerce_version_message', 0 ) ;    
        return;
    } else {
        return;
    }
}

Tetapi cara yang lebih baik untuk menimpanya adalah dengan menginstal runkit( https://github.com/padraic/runkit ) dan kemudian langsung menggantinya di "functions.php" tema Anda:

add_action( 'init', function () {
    $code = <<<'EOD'
echo "O la la";
EOD;
    runkit_method_redefine(
        'WCPGSK_Main',
        'wcpgsk_email_after_order_table',
        '$order',
        $code,
        RUNKIT_ACC_PUBLIC
    );
} );

(Itu lelucon, btw.)

bonger
sumber