Cum înlocuiesc o funcție, declarată într-o clasă de plugin, în functions.php?

29 iul. 2015, 18:25:43
Vizualizări: 33.5K
Voturi: 11

Vreau să modific o funcție dintr-un plugin. Aceasta este declarată în fișierul principal al plugin-ului astfel:

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

Și este apelată de acolo astfel:

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

Presupun că ar fi posibil să o înlocuiesc dacă aș avea acces la clasă în functions.php. Apoi aș putea scrie ceva de genul:

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

Gândul meu pentru a obține acces la clasă în fișierul functions.php a fost să includ fișierul unde este declarată clasa în functions.php:

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

Dar acest lucru nu funcționează deoarece fișierul plugin-ului este inclus când plugin-ul este inițializat în WordPress, presupun.

Există vreo modalitate de a rescrie funcția fără a modifica fișierele plugin-ului?

0
Toate răspunsurile la întrebare 3
1
12

Dacă plugin-ul tău este înregistrat astfel:

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

Atunci ar trebui să poți elimina filtrul accesând variabila 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();

În caz contrar, va trebui să parcurgi variabila globală $wp_filter pentru a găsi cheia de înregistrare:

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

Această metodă consumă resurse și ar trebui folosită doar dacă nu ai altă opțiune.

29 iul. 2015 21:19:19
Comentarii

Acesta ar trebui să fie răspunsul acceptat. Este mai util în general și nu se limitează doar la cazul specific al OP.

David R. David R.
23 aug. 2016 13:45:01
3

Acest lucru ar trebui să funcționeze:

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

}
29 iul. 2015 18:50:10
Comentarii

există o funcție remove_action: https://codex.wordpress.org/Function_Reference/remove_action

Alex Older Alex Older
29 iul. 2015 19:10:47

Da, asta mi-a scăpat, acest plugin are o variabilă care poate fi accesată ca una globală. Prostia mea. Mulțumesc pentru răspuns, aceasta funcționează în acest caz particular (pentru acest plugin).

Igor Skoldin Igor Skoldin
30 iul. 2015 19:18:10

Alex Older a legat locul care explică de ce funcționează răspunsul său. remove_action acceptă un array cu clasa statică sau instanța în cadrul căreia dorești să elimini o metodă.

ninja08 ninja08
7 mar. 2017 23:36:57
0

Acest plugin face funcția sa de inițializare wcpgsk_init() pluggable (supra-scriabilă), deci un alt mod de a o suprascrie este să o definiți mai întâi într-un plugin must-use (deoarece este prea târziu în "functions.php" al temei). Puteți pune suprascrierea în "wp-content/mu-plugins/functions.php":

function wcpgsk_init() {
    global $wcpgsk, $wcpgsk_about, $wcpgsk_options, $wcpgsk_session, $wcpgsk_woocommerce_active;    
    //continuă încărcarea doar dacă
    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;

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

        //încarcă în variabila noastră 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;
    }
}

Dar o metodă chiar mai bună de a o suprascrie este să instalați runkit (https://github.com/padraic/runkit) și apoi să o înlocuiți direct în "functions.php" al temei:

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

(Asta e o glumă, apropo.)

30 iul. 2015 10:05:52