Comment remplacer une fonction, déclarée dans la classe d'un plugin, dans functions.php?

9

Je souhaite modifier une fonction dans un plugin. Il est déclaré dans le fichier principal du plugin comme ceci:

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

Ajoutez appelé à partir de là comme ceci:

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

Je suppose qu'il serait possible de le remplacer s'il avait un accès à la classe dans functions.php. Ensuite, je serais en mesure d'écrire quelque chose comme ça:

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

Ma pensée pour obtenir un accès à la classe dans le fichier functions.php était d'inclure le fichier où la classe est déclarée dans functions.php:

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

Mais cela ne fonctionne pas parce que le fichier du plugin est inclus lorsque le plugin est initialisé dans WordPress, je suppose.

Existe-t-il un moyen de réécrire la fonction sans toucher aux fichiers du plugin?

Igor Skoldin
la source

Réponses:

8

Cela devrait fonctionner:

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
la source
1
il y a une fonction remove_action: codex.wordpress.org/Function_Reference/remove_action
Alex Older
Oui, c'est ce que j'ai manqué, ce plugin a une variable accessible en tant que variable globale. Ma stupidité. Merci pour votre réponse, cela fonctionne dans ce cas particulier (pour ce plugin).
Igor Skoldin
Alex Older lié à l'endroit qui explique pourquoi sa réponse fonctionne. L'action remove_action accepte un tableau avec la classe statique ou d'instance dans laquelle vous souhaitez supprimer une méthode.
ninja08
11

Si votre plugin est enregistré comme ceci:

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

Ensuite, vous devriez pouvoir supprimer le filtre en accédant au 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();

Sinon, vous devrez explorer la $wp_filter globalclé d'enregistrement:

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

Cela demande beaucoup de ressources et ne devrait vraiment pas être fait à moins que vous n'ayez pas d'autre choix.

s_ha_dum
la source
2
Cela devrait être la réponse acceptée. Ceci est plus généralement utile et ne se limite pas au cas spécifique d'OP.
David R.
1

Ce plugin rend sa fonction init wcpgsk_init()enfichable, donc une autre façon de le remplacer est de le définir d'abord dans un plugin indispensable (car il est trop tard dans le "functions.php" de votre thème). Vous pouvez donc mettre votre priorité dans "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;
    }
}

Mais un meilleur moyen de le remplacer est d'installer runkit( https://github.com/padraic/runkit ) et de le remplacer directement dans le "functions.php" de votre thème:

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

(C'est une blague, au fait.)

bonger
la source