Làm cách nào để thay thế một hàm, được khai báo bên trong lớp của plugin, trong Hàm.php?


9

Tôi muốn sửa đổi một chức năng trong một plugin. Nó được khai báo trong tệp chính của plugin như thế này:

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

Thêm được gọi từ đó như thế này:

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

Tôi đoán nó sẽ có thể thay thế nó nếu có quyền truy cập vào lớp trong hàm.php. Sau đó, tôi sẽ có thể viết một cái gì đó như thế này:

$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') );

Tôi nghĩ rằng để có được quyền truy cập vào lớp trong tệp tin.php. Bao gồm tệp mà lớp được khai báo trong hàm.php:

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

Nhưng điều này không hoạt động vì tập tin của plugin được bao gồm khi plugin đang được khởi tạo trong WordPress, tôi đoán vậy.

Có cách nào để viết lại chức năng mà không cần chạm vào các tập tin của plugin không?

Câu trả lời:


8

Điều này sẽ làm việc:

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' ) );

}


Vâng, đó là tôi đã bỏ lỡ, plugin này có một biến có thể truy cập dưới dạng toàn cầu. Sự ngu ngốc của tôi. Cảm ơn câu trả lời của bạn, điều này đang hoạt động trong trường hợp cụ thể này (đối với plugin này).
Igor Skoldin

Alex Cũ liên kết đến nơi giải thích lý do tại sao câu trả lời của ông hoạt động. Remove_action chấp nhận một mảng với lớp tĩnh hoặc thể hiện trong đó bạn muốn xóa một phương thức.
ninja08

11

Nếu plugin của bạn được đăng ký như thế này:

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();

Sau đó, bạn sẽ có thể xóa bộ lọc bằng cách truy cập toàn cầu:

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();

Nếu không, bạn sẽ cần phải thu thập thông tin $wp_filter globalcho khóa đăng ký:

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();

Đây là tài nguyên chuyên sâu và thực sự không nên được thực hiện trừ khi bạn không có lựa chọn nào khác.


2
Đây phải là câu trả lời được chấp nhận. Điều này thường hữu ích hơn và không chỉ giới hạn trong trường hợp cụ thể của OP.
David R.

1

Plugin đó làm cho chức năng init của nó wcpgsk_init()có thể cắm được, vì vậy một cách khác để ghi đè lên nó là xác định nó trước tiên trong một plugin phải sử dụng (vì đã quá muộn trong "tests.php" của chủ đề của bạn). Vì vậy, bạn có thể đặt ghi đè của mình vào "wp-content / mu-plugins / tests.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;
    }
}

Nhưng một cách thậm chí tốt hơn để ghi đè nó là cài đặt runkit( https://github.com/padraic/runkit ) và sau đó chỉ cần thay thế trực tiếp trong "hàm.php" của chủ đề của bạn:

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
    );
} );

(Đó là một trò đùa, btw.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.