Wie ersetze ich eine Funktion, die in der Klasse eines Plugins deklariert ist, in functions.php?

9

Ich möchte eine Funktion in einem Plugin ändern. Es wird in der Hauptdatei des Plugins wie folgt deklariert:

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

Add von dort wie folgt aufgerufen:

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

Ich denke, es wäre möglich, es zu ersetzen, wenn man Zugriff auf die Klasse in functions.php hätte. Dann könnte ich so etwas schreiben:

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

Mein Gedanke, einen Zugriff auf die Klasse in der Datei functions.php zu erhalten, war, die Datei einzuschließen, in der die Klasse in functions.php deklariert ist:

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

Dies funktioniert jedoch nicht, da die Datei des Plugins enthalten ist, wenn das Plugin in WordPress initialisiert wird.

Gibt es eine Möglichkeit, die Funktion neu zu schreiben, ohne die Dateien des Plugins zu berühren?

Igor Skoldin
quelle

Antworten:

8

Das sollte funktionieren:

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
quelle
1
Es gibt eine Funktion remove_action: codex.wordpress.org/Function_Reference/remove_action
Alex Older
Ja, das habe ich vermisst, dieses Plugin hat eine Variable, auf die als globale zugegriffen werden kann. Meine Dummheit. Vielen Dank für Ihre Antwort, dies funktioniert in diesem speziellen Fall (für dieses Plugin).
Igor Skoldin
Alex Older ist mit dem Ort verbunden, der erklärt, warum seine Antwort funktioniert. Die remove_action akzeptiert ein Array mit der statischen oder Instanzklasse, in der Sie eine Methode entfernen möchten.
Ninja08
11

Wenn Ihr Plugin wie folgt registriert ist:

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

Dann sollten Sie in der Lage sein, den Filter zu entfernen, indem Sie auf die globale Datei zugreifen:

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

Andernfalls müssen Sie $wp_filter globalden Registrierungsschlüssel crawlen:

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

Dies ist ressourcenintensiv und sollte nur durchgeführt werden, wenn Sie keine andere Wahl haben.

s_ha_dum
quelle
2
Dies sollte die akzeptierte Antwort sein. Dies ist allgemeiner nützlich und nicht nur auf den speziellen Fall von OP beschränkt.
David R.
1

Dieses Plugin macht seine Init-Funktion wcpgsk_init()steckbar. Eine andere Möglichkeit, es zu überschreiben, besteht darin, es zuerst in einem Plugin zu definieren, das unbedingt verwendet werden muss (da es in der "functions.php" Ihres Themas zu spät ist). Sie können Ihren Override also in "wp-content / mu-plugins / functions.php" einfügen:

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

Eine noch bessere Möglichkeit, es zu überschreiben, besteht darin, es zu installieren runkit( https://github.com/padraic/runkit ) und es dann direkt in der "functions.php" Ihres Themas zu ersetzen:

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

(Das ist übrigens ein Witz.)

Bonger
quelle