Cum înlocuiesc o funcție, declarată într-o clasă de plugin, în functions.php?
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?
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.

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

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

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).

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.)
