Remove Woocommerce action from external plugin - php

I'm switching to a new Wordpress plugin I've written myself that will run along side an old plugin on top of the Woocommerce cart. While I'm running the two plugins I want to remove the old plugin's action that calls it's table to display in the users my account page. I will be adding logic after to work out if it's needed, but for now I just need to remove it.
This is how the action is being called in the old plugin.
class WC_Subscriptions {
public static function init() {
// Display Subscriptions on a User's account page
add_action( 'woocommerce_before_my_account', __CLASS__ . '::get_my_subscriptions_template' );
}
}
WC_Subscriptions::init();
So far in my own plugin I have called the following and none of them work.
remove_action( 'woocommerce_before_my_account', array('WC_Subscriptions', 'get_my_subscriptions_template' ) );
// no error but still shows the table
and the last one
remove_action( 'woocommerce_before_my_account', array( WC_Subscriptions::init(), 'get_my_subscriptions_template' ) );
// Fatal error: Class 'WC_Subscriptions' not found in /var/sites/XXXXX on line 45
I have tried changing/adding the $priority from 1, 9, 10, 11 and 99 and that doesn't work either.
It's frustrating as I'm sure it would work if the old plugin was initiated with a new instance so I could do this
global $my_class;
remove_action( 'woocommerce_before_my_account', array( $my_class, 'get_my_subscriptions_template' ) );
Can anyone help?

This always happens, just worked it out.
I needed to hook the remove_action into another action that is called much later.
In the end I did this
class My_new_plugin {
public function __construct() {
add_action( 'wp_head', array($this, 'remove_action_woosubscription_table' ) );
}
public function remove_action_woosubscription_table() {
remove_action( 'woocommerce_before_my_account', array( 'WC_Subscriptions', 'get_my_subscriptions_template' ) );
}
}

You can set third attribute 'priority' as 999
<?php remove_action( $tag, $function_to_remove, $priority ); ?>

Related

Remove action from a plugin

We use a plugin which add a filter to hide some order meta. Now we want to remove them via child theme instead of editing the plugin file. I tried every answer from here but the action is not removed: https://wordpress.stackexchange.com/questions/240929/how-to-remove-action-from-plugin and Removing action added by a plugin in Wordpress
This is the Plugin function:
public function __construct() {
add_filter( 'woocommerce_order_item_get_formatted_meta_data', [ $this, 'hide_extra_data' ] );
}
I tried with that already, but I'm not sure if this is the right way to do it.
add_action( 'woocommerce_order_item_get_formatted_meta_data', 'remove_my_action', 1 );
function remove_my_action(){
remove_action('woocommerce_order_item_get_formatted_meta_data', 'hide_extra_data', 10, 1);
}
remove_action( 'wp_fwoocommerce_order_item_get_formatted_meta_dataooter', 'hide_extra_data', 1 );
Try like this:
add_action( 'plugins_loaded', 'webearth_remove_plugin_filter' );
function webearth_remove_plugin_filter() {
remove_filter( 'woocommerce_order_item_get_formatted_meta_data',
array('ClassName', 'hide_extra_data'),
10 );
}
Change ClassName with the name of the class used by the plugin, the Class where the constructor is.

Replace/Overwrite wordpress plugin class function

I am trying to replace or overwrite an action hook declared inside a wordpress plugin class
class WCFM_Withdrawal {
public function __construct() {
global $WCFM;
// WCFMu Thirdparty Ajax Controller
add_action( 'after_wcfm_ajax_controller', array( &$this, 'wcfm_withdrawal_ajax_controller' ) );
}
Here the add_action hook which points the function. I want to replace "wcfm_withdrawal_ajax_controller" with my own function.
add_action("init", function () {
// removing the woocommerce hook
global $WCFM;
remove_action( 'after_wcfm_ajax_controller', array( $WCFM, 'wcfm_withdrawal_ajax_controller' ) );
});
add_action( 'after_wcfm_ajax_controller', 'my_new_function' );
function my_new_function(){
//Do something here
}
i have tried to remove_action and add my own function, but didn't work.
Make sure you have the correct Class instance. Your example shows $WCFM, but the class declaration is WCFM_Withdrawal. Is $WCFM an instance of WCFM_Withdrawal? If you have determined that you do have the appropriate class instance, you may be running the remove_action too early (before the one you want to remove is added).
You can try lowering the priority of your init function:
add_action( 'init', function () {
// removing the woocommerce hook
global $WCFM;
remove_action( 'after_wcfm_ajax_controller', array( $WCFM, 'wcfm_withdrawal_ajax_controller' ) );
}, 99 );
I'd say you could also try a later Action Hook than init, but since this appears to be an AJAX handler, that probably won't suffice. Start by making sure that you've got the correct class instance variable, and then bump down the priority of your removal.

Send Woocommerce email on custom action not working

I'm trying to send a custom email when a post is published using the Woocommerce email template.
I have included the template and class which Woocommerce loads using the woocommerce_email_classes and have also registered the custom action send_entry_list in the woocommerce_email_actions filter.
do_action('send_entry_list', $competition_id, $entry_list_url);
When adding add_action to this within the class-entry-list-email.php which triggers the email, it's not printing out 'triggered' in the debug.log file.
Does anyone know why this isn't firing?
public function __construct() {
add_action( 'send_entry_list', array( $this, 'trigger' ) );
}
public function trigger( $competition_id, $entry_list_url ) {
error_log(print_r('triggered', true));
}
add_filter( 'woocommerce_email_classes', array($this, 'add_draw_number_email'));
function add_draw_number_email( $email_classes ) {
// include our custom email class
require( 'includes/class-entry-list-email.php' );
// add the email class to the list of email classes that WooCommerce loads
$email_classes['Entry_List_Email'] = new Entry_List_Email();
return $email_classes;
}
add_filter( 'woocommerce_email_actions', array($this, 'crwc_register_custom_order_status_action'));
function crwc_register_custom_order_status_action( $actions ) {
$actions[] = 'send_entry_list';
return $actions;
}
Actually, you are missing _notification in the add_action hook. In WooCommerce email, you need to add _notification in the tag name of do_action.
In your case, you are using send_entry_list in both do_action and add_action whereas in add_action you just need to append _notification in the tag name so hook name becomes send_entry_list_notification.
To make this easy for you just do the following change.
Replace this line:
add_action( 'send_entry_list', array( $this, 'trigger' ) );
with this:
add_action( 'send_entry_list_notification', array( $this, 'trigger' ), 10, 2 );
Hope, it works for you.
Change hook as below and try,
add_action( 'send_entry_list', array( $this, 'trigger' ), 10, 2 );

Wordpress dequeue scripts without handle?

I'm currently using Foobox lightbox (free) plugin, and apparently the plugins' files are loaded on every page regardless of whether it's used or not. However I would like to change this, but I can't seem to find any handles to dequeue the scripts through.
It seems that the scripts are called by the code beneath, which to me at least, doesn't show any handles. I've tried using remove_action(...) to "counter" them as well as various inputs in wp_dequeue_script() to try and target the files directly - e.g. wp_dequeue_script('foobox.free.min.js')
class Foobox_Free extends Foo_Plugin_Base_v2_1 {
const JS = 'foobox.free.min.js';
const CSS = 'foobox.free.min.css';
const CSS_NOIE7 = 'foobox.noie7.min.css';
const FOOBOX_URL = 'http://fooplugins.com/plugins/foobox/?utm_source=fooboxfreeplugin&utm_medium=fooboxfreeprolink&utm_campaign=foobox_free_pro_tab';
const BECOME_AFFILIATE_URL = 'http://fooplugins.com/affiliate-program/';
private static $instance;
public static function get_instance() {
if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Foobox_Free ) ) {
self::$instance = new Foobox_Free();
}
return self::$instance;
}
/**
* Initialize the plugin by setting localization, filters, and administration functions.
*/
private function __construct() {
//init FooPluginBase
$this->init( FOOBOXFREE_FILE, FOOBOXFREE_SLUG, FOOBOX_BASE_VERSION, 'FooBox FREE' );
if (is_admin()) {
add_action('admin_head', array($this, 'admin_inline_content'));
add_action('foobox-free-settings_custom_type_render', array($this, 'custom_admin_settings_render'));
new FooBox_Free_Settings();
add_action( FOOBOX_ACTION_ADMIN_MENU_RENDER_GETTING_STARTED, array( $this, 'render_page_getting_started' ) );
add_action( FOOBOX_ACTION_ADMIN_MENU_RENDER_SETTINGS, array( $this, 'render_page_settings' ) );
add_action( 'admin_notices', array( $this, 'admin_notice_foogallery_lightboxes' ) );
add_action( 'wp_ajax_foobox_foogallery_lightboxes_ignore_notice', array( $this, 'admin_notice_foogallery_lightboxes_ignore' ) );
add_action( 'wp_ajax_foobox_foogallery_lightboxes_update', array( $this, 'admin_notice_foogallery_lightboxes_update' ) );
add_action( 'admin_print_scripts', array( $this, 'admin_notice_foogallery_lightboxes_inline_js' ), 999 );
add_filter( 'foobox-free-has_settings_page', '__return_false' );
} else {
// Render JS to the front-end pages
add_action('wp_enqueue_scripts', array($this, 'frontend_print_scripts'), 20);
add_action('foobox-free_inline_scripts', array($this, 'inline_dynamic_js'));
// Render CSS to the front-end pages
add_action('wp_enqueue_scripts', array($this, 'frontend_print_styles'));
if ( $this->is_option_checked('disable_others') ) {
add_action('wp_footer', array($this, 'disable_other_lightboxes'), 200);
}
}
}
How, if possible, do I dequeue these scripts (and styles) without editing the plugin file directly?
Edit
Below I've added the things I've tried doing to remove the scripts (all added to functions.php):
add_action( 'wp_enqueue_scripts', 'remove_foobox_scripts', 100 );
function remove_foobox_scripts() {
if ( !is_page('my-page') ) {
wp_deregister_script( 'foobox.free.min.js' );
wp_dequeue_script( 'foobox.free.min.js' );
}
}
Also tried the below, which is just a straight copy from the foobox file:
remove_action('wp_enqueue_scripts', array($this, 'frontend_print_scripts'), 20);
remove_action('foobox-free_inline_scripts', array($this, 'inline_dynamic_js'));
remove_action('wp_enqueue_scripts', array($this, 'frontend_print_styles'));
Also tried the below, where the array( part is removed:
remove_action('wp_enqueue_scripts','frontend_print_scripts', 20);
remove_action('foobox-free_inline_scripts', 'inline_dynamic_js');
remove_action('wp_enqueue_scripts', 'frontend_print_styles');
The problem with the way you are trying to do this stems from the order in which things happen in Wordpress.
You are relying on the conditional tags like is_page('my-page') to determine whether or not to load the plugin. These conditional tags do not become available until Wordpress has parsed the URL for the current query, and at this point all the plugins and your theme have already been loaded. Even if you parse the URL yourself instead of using the conditional tags you cannot be sure your code will run before the plugins are loaded.
The solution is to add your code as an mu-plugin. These are loaded before normal plugins so you can use an option (option name) filter here to alter the plugins you want to be loaded.
Option filters pass an array to your function containing the values which are set for that option, so in this case you want to hook option_active_plugins.
You can find the values to use for by running print_r(get_option('active_plugins')); or look through the plugins folder of your wordpress install.
The following example is specific to your question, but you could modify it to make a more comprehensive set of rules, adding and removing multiple plugins on different pages based on many conditions.
My function checks you are not in wp-admin and then has 2 conditions. The first disables a normally active plugin on the specified pages, the second enables a normally disabled plugin on the specified pages.
<?php
add_filter( 'option_active_plugins', 'add_or_remove_plugins' );
function add_or_remove_plugins( $plugins ) {
if (strpos( $_SERVER['REQUEST_URI'], '/wp-admin/' ) !== 0) { // Disable in admin pages or admin plugin settings stop working properly
if (strpos( $_SERVER['REQUEST_URI'], '/remove-plugin-here/' ) === 0) { // Conditonal tags still unavailable so you have to parse urls yourself
$k = array_search( 'foobox-image-lightbox/foobox-free.php', $plugins ); // This will stop an active plugin from loading
if( false !== $k ){
unset( $plugins[$k] );
}
}
if (strpos( $_SERVER['REQUEST_URI'], '/add-plugin-here/' ) === 0) {
$plugins[] = 'foobox-image-lightbox/foobox-free.php'; // This will load the plugin along with all the active plugins
}
}
return $plugins;
}
?>
To install just change the values to suit, paste into a file and upload into your mu-plugins folder
EDIT
Looks like your inline js is added to wp_head during the constructor of the Foobox_Free class. You could try adding this to your functions.php:
add_action( 'wp_head', 'remove_dynamic_js' );
function remove_dynamic_js(){
$foo = Foobox_Free::getInstance();
remove_action('wp_head', array($foo, 'inline_dynamic_js'));
}
or if that doesn't work then maybe this:
add_action( 'wp_head', 'remove_dynamic_js' );
function remove_dynamic_js(){
remove_action('wp_head', array('Foobox_Free', 'inline_dynamic_js'));
}
The action is added inside a private function, so I don't know if either of those will actually work. Give it a shot. If not my first answer will as it stops the plugin from loading at all on the specified pages.
UPDATE
Well, I was close... Here's the code to remove the scripts, as supplied by the plugin author.
$foobox = Foobox_Free::get_instance();
remove_action('foobox-free_inline_scripts', array($foobox, 'inline_dynamic_js'));

need help removing action from plugin file

Hello I am trying to remove an action from a wordpress plugin file. The plugin is called Woocommerce Points and Rewards. I have found the action I want to remove in one of the class files. When I comment out the "add_action" it does exactly what I want. But I am trying to remove the action from functions.php in my child them. I have been reading on this and I think my problem is I need to "globalize" the class variable that the action is in; but I am not sure what that class variable is…
here is the code where it adds the action (part of a file):
class WC_Points_Rewards_Cart_Checkout {
/**
* Add cart/checkout related hooks / filters
*
* #since 1.0
*/
public function __construct() {
// Coupon display
add_filter( 'woocommerce_cart_totals_coupon_label', array( $this, 'coupon_label' ) );
// Coupon loading
add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'points_last' ) );
add_action( 'woocommerce_applied_coupon', array( $this, 'points_last' ) );
// add earn points/redeem points message above cart / checkout
add_action( 'woocommerce_before_cart', array( $this, 'render_earn_points_message' ), 15 );
add_action( 'woocommerce_before_cart', array( $this, 'render_redeem_points_message' ), 16 );
add_action( 'woocommerce_before_checkout_form', array( $this, 'render_earn_points_message' ), 5 );
add_action( 'woocommerce_before_checkout_form', array( $this, 'render_redeem_points_message' ), 6 );
// handle the apply discount submit on the cart page
add_action( 'wp', array( $this, 'maybe_apply_discount' ) );
// handle the apply discount AJAX submit on the checkout page
add_action( 'wp_ajax_wc_points_rewards_apply_discount', array( $this, 'ajax_maybe_apply_discount' ) );
}
The function I want to remove is this one:
add_action( 'woocommerce_before_cart', array( $this, 'render_redeem_points_message' ), 16 );
so far no luck in getting it removed; here is what I have in functions.php:
global $woocommerce, $wc_points_rewards;
/*
global $this;
*/
remove_action( 'woocommerce_before_cart', array( $this, 'render_redeem_points_message' ), 16 );
so - I am sure this can be done in this way at least I have read that it can be done, I think I just have some thing wrong on this…
I tried globalizing $this, but that just gave me an error message...
if you need to see the entire file or something else please just let me know…
So I am hoping someone on here can help me identify what I am doing wrong…
** UPDATE Monday 8/18 ********
Looking for where class is instantiated; I have found this in the "woo commerce-points-and-rewards.php" file; this looks like this may be it but not sure what I am looking at;
does this look like where the "WC_Points_Rewards_Cart_Checkout" is instantiated?
And if so I am not sure how i use this to write my "remove action" in functions.php...
private function includes() {
// product class
require( 'classes/class-wc-points-rewards-product.php' );
$this->product = new WC_Points_Rewards_Product();
// cart / checkout class
require( 'classes/class-wc-points-rewards-cart-checkout.php' );
$this->cart = new WC_Points_Rewards_Cart_Checkout();
// order class
require( 'classes/class-wc-points-rewards-order.php' );
$this->order = new WC_Points_Rewards_Order();
// discount class
require( 'classes/class-wc-points-rewards-discount.php' );
$this->discount = new WC_Points_Rewards_Discount();
// actions class
require( 'classes/class-wc-points-rewards-actions.php' );
$this->actions = new WC_Points_Rewards_Actions();
// manager class
require( 'classes/class-wc-points-rewards-manager.php' );
// points log access class
require( 'classes/class-wc-points-rewards-points-log.php' );
if ( is_admin() )
$this->admin_includes();
}
Thanks so much...
Try this:
// Use the class name instead of a globalized $this
remove_action( 'woocommerce_before_cart', array( 'WC_Points_Rewards_Cart_Checkout', 'render_redeem_points_message' ), 16 );
As $this is an internal referrer to the class it is used in, globalizing it may not be a good thing.
Does the plugin allow you to extend the class with your own and use it instead?
you found a solution for this? having the same problem with another wc plugin ;)
alright. found an answer in the wc docs. in my case:
function wc_move_checkout_addons() {
remove_action( 'woocommerce_checkout_after_customer_details', array( $GLOBALS['wc_checkout_add_ons']->frontend, 'render_add_ons' ) );
add_action( 'woocommerce_checkout_before_customer_details', array( $GLOBALS['wc_checkout_add_ons']->frontend, 'render_add_ons' ) );
}
add_action( 'init', 'wc_move_checkout_addons' );
so in your case it should be something like that:
function wc_remove_message() {
remove_action( 'woocommerce_before_cart', array( $GLOBALS['wc_points_rewards_cart_checkout']->frontend, 'render_redeem_points_message' ) );
}
add_action( 'init', 'wc_remove_message' );
In case anyone else is wondering, I just accomplished removing the action in this plugin in the following way.
I wanted to remove the action defined in class-wc-points-rewards.php on line 34:
add_action( 'woocommerce_single_product_summary', array( $this, 'render_product_message' ) );
To do that, I looked at woocommerce-points-and-rewards.php. On line 46 it shows:
$GLOBALS['wc_points_rewards'] = new WC_Points_Rewards();
And in the same file for the definition of the WC_Points_Rewards class, on line 249-250 it shows:
require( 'includes/class-wc-points-rewards-product.php' );
$this->product = new WC_Points_Rewards_Product();
With that information, I was able to remove the action:
remove_action( 'woocommerce_single_product_summary', array( $GLOBALS['wc_points_rewards']->product, 'render_product_message' ) );
I was able to figure out how to remove the render_redeem_points_message effectively with the following code:
/* Removes render_redeem_points_message() */
function wc_remove_points_message() {
global $woocommerce;
global $wc_points_rewards;
// Removes message from cart page
remove_action( 'woocommerce_before_cart', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 16 );
// Removes message from checkout page
remove_action( 'woocommerce_before_checkout_form', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 6 );
}
// Removes action on init
add_action( 'init', 'wc_remove_points_message' );
To share a bit more, I wanted to create a minimum purchase amount to be able to redeem points:
/* Adds Minimum Order for Points Redemption */
function wc_min_order_points_message() {
global $woocommerce;
global $wc_points_rewards;
// Get cart subtotal, excluding tax
$my_cart_total = $woocommerce->cart->subtotal_ex_tax;
if ($my_cart_total < 30) { // $30 minimum order
remove_action( 'woocommerce_before_cart', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 16 );
remove_action( 'woocommerce_before_checkout_form', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 6 );
} // endif $my_cart_total
}
// Adds action for cart and checkout pages instead of on init
add_action( 'woocommerce_before_cart', 'wc_min_order_points_message' );
add_action( 'woocommerce_before_checkout_form', 'wc_min_order_points_message' );
I hope this helps anyone else trying to similarly expand on the WooCommerce Points and Rewards plugin.
SOLUTION-1:
In this case, as we have the plugin object's global instance, then we can do it easily:
remove_action('woocommerce_before_cart',array($GLOBALS['wc_points_rewards']->cart,'render_redeem_points_message'),16);
SOLUTION-2:
We will not be lucky always like the above solution getting the instance of the class object if any plugin author creates the class object anonymously without storing it to any global variables or keeping no method which can return it's own instance. In those cases, we can use the following :)
//keeping this function in our functions.php
function remove_anonymous_object_action( $tag, $class, $method, $priority=null ){
if( empty($GLOBALS['wp_filter'][ $tag ]) ){
return;
}
foreach ( $GLOBALS['wp_filter'][ $tag ] as $filterPriority => $filter ){
if( !($priority===null || $priority==$filterPriority) )
continue;
foreach ( $filter as $identifier => $function ){
if( is_array( $function)
and is_a( $function['function'][0], $class )
and $method === $function['function'][1]
){
remove_action(
$tag,
array ( $function['function'][0], $method ),
$filterPriority
);
}
}
}
}
And calling the following line appropriately when we need (may be with a hook or something):
//-->Actual Target: this line does not work;
//remove_action( 'personal_options', array('myCRED_Admin','show_my_balance') );
//-->But instead this line will work ;)
remove_anonymous_object_action('personal_options','myCRED_Admin','show_my_balance');
exactly this function worked for me
if (class_exists('WC_Points_Rewards')) {
global $woocommerce, $wc_points_rewards;
remove_action( 'woocommerce_before_cart', array( $wc_points_rewards->cart, 'render_earn_points_message' ), 15 );
remove_action( 'woocommerce_before_cart', array( $wc_points_rewards->cart, 'render_redeem_points_message' ), 16 );
}

Categories