Have you got an idea how to remove actions or filters in Wordpress (from a plugin in my case) when those are defined like so:
add_action('action_tag', function(){...});
or
add_filter('filter_tag', function(){...});
They are defined inside the function add_action or add_filter so I have no clue witch 'function_name' I should use to remove it.
remove_action($tag, what am I supposed to put in here?, $priority);
You are talking about anonymous functions. To remove anonymous functions from filters or actions, you have to use the same function body and priority you used when they were added like so:
// Add it.
add_filter( 'tag', function ( $param ) {
return $param;
}, 10, 1 );
// Remove it.
remove_filter( 'tag', function ( $param ) {
return $param;
}, 10 );
try this.. This will delete all hooks that are anonymous functions
global $wp_filter;
foreach ( $wp_filter as $filter_name => $filter_properties ):
foreach ( $filter_properties->callbacks as $priority ):
foreach( $priority as $function ):
if( is_object( $function["function"] ) == true ):
unset( $wp_filter[ $filter_name ] );
endif;
endforeach;
endforeach;
endforeach;
Related
I've combined the shortcodes for checkout and cart onto the Checkout page in two columns to reduce the number of clicks to finish payment.
However, I'm finding that hooks seem to act strangely with this arrangement.
For example, I'm trying to place the cross-sell section below the cart section. On the default cart page, it appears by default. Combining cart and checkout together makes it disappear.
The logical approach is to do this:
function add_cart_collaterals() {
if (is_checkout()) {
add_action( 'woocommerce_after_cart_contents', 'woocommerce_cross_sell_display' );
}
}
add_action('wp', 'add_cart_collaterals');
That did nothing.
Out of desperation, I then copied and adapted the cross-sell.php template code and put it directly into my child theme's functions.php file like this:
/* Display Cross-Sells below cart */
function show_cross_sell() {
if ( $cross_sells ) :
echo '<div class="cross-sells"><h2>';
_e( 'You may be interested in…', 'woocommerce' );
echo '</h2>';
woocommerce_product_loop_start();
foreach ( $cross_sells as $cross_sell ) :
$post_object = get_post( $cross_sell->get_id() );
setup_postdata( $GLOBALS['post'] =& $post_object );
wc_get_template_part( 'content', 'product' );
endforeach;
woocommerce_product_loop_end();
echo '</div>';
else : {
echo 'No cross sells to display';
}
endif;
}
add_action( 'woocommerce_after_cart_table', 'show_cross_sell', 10 );
But, only the else condition runs and displays "No cross sells to display". So maybe it lost scope on the $cross_sells object.
Is there any hope of my being able to achieve this?
WooCommerce support came through with an answer that helped me. I wasn't assigning $cross_sells to anything. I needed to assign it like this $cross_sells = array_filter( array_map( 'wc_get_product', WC()->cart->get_cross_sells() ), 'wc_products_array_filter_visible' );
But I'm still curious to know why the hook action wasn't working.
As to why you couldn't achieve it with the hook, it's probably because of the first line of code in the function that you hooked into that action:
function woocommerce_cross_sell_display( $limit = 2, $columns = 2, $orderby = 'rand', $order = 'desc' ) {
if ( is_checkout() ) {
return;
}
I'm trying to override a plugin class on a WordPress plugin.
Here is the original plugin class :
class WCV_Vendor_Dashboard
{
/**
* __construct()
*/
function __construct()
{
add_shortcode( 'wcv_shop_settings', array( $this, 'display_vendor_settings' ) );
add_shortcode( 'wcv_vendor_dashboard', array( $this, 'display_vendor_products' ) );
add_action( 'template_redirect', array( $this, 'check_access' ) );
add_action( 'init', array( $this, 'save_vendor_settings' ) );
}
public function save_vendor_settings(){
//some codes here
}
}
Here is what I'm trying (in functions.php), but it doesn't work :
$wcv_vendor_dashboard = new WCV_Vendor_Dashboard();
global $wcv_vendor_dashboard;
remove_action( 'init', array( $wcv_vendor_dashboard , 'save_vendor_settings' ) );
How to remove it correctly and how to create the replacement?
Additional info:
I did similar thing on the WooCommerce core. When I want to override a class / function, I use this (for example):
remove_action( 'template_redirect', array( 'WC_Form_Handler', 'save_account_details' ) );
function new_save_account_details() {
//custom code here
}
add_action( 'template_redirect', 'new_save_account_details' );
It's working properly on WooCommerce core. I tried something similar on WCV_Vendor_Dashboard but it doesn't work.
Why it was working with woocommerce, but it does not work in this case?
When you attach a function on to a specific action, WoredPress creates unique id for that callback and stores that in global $wp_filter array ( in fact, it was an array before, but now it is an object ). For object method callbacks ( like array( $this, 'save_vendor_settings' ) ), the id is generated with spl_object_hash php function. For the above example,
spl_object_hash( $this ) . 'save_vendor_settings'
, and it looks like 000000001c0af63f000000006d7fe83asave_vendor_settings.
To "legally" remove the object method with remove_action() you will need to have access to the original object that was used to attach the function in the first place. If the object exists in global namespace:
global $wcv;
remove_action( 'init', array( $wcv, 'save_vendor_settings' ) );
Creating another class instance will not work because the generated id is unique for each object, even if they are instances of the same class.
In the case of WooCommerce I guess it was about static class methods. Different logic is used to generate the ids for static class methods, functions and static method callbacks are just returned as strings. For your example it would be:
'WC_Form_Handler' . '::' . 'save_account_details'
You see why it works for one case, but not for the other.
There is a hack to replace functions attached by replacing them directly in global $wp_filter object, but it's not 100% reliable. Since we do not have access to the original object, we can only filter $wp_filter by the name of the function, if there are identical names for the same action it will replace wrong handlers.
global $wp_filter;
foreach ( $wp_filter['init']->callbacks as $priority => &$callbacks ) {
foreach ( $callbacks as $id => &$callback ) {
if ( substr( $id, -strlen( 'save_vendor_settings' ) ) === 'save_vendor_settings' ) {
// replace the callback with new function
$callback['function'] = 'new_save_vendor_settings';
}
}
}
I hope it will work, greetings.
Example for child class
class WCV_Vendor_Dashboard_Child extends WCV_Vendor_Dashboard
{
/**
* __construct()
*/
function __construct()
{
parent::__construct();
}
public function new_save_vendor_settings(){
//some codes here
}
}
I'm struggling with one thing. I've got such wordpress function:
function wpq_insert_attachment_data($data, $postarr){
if (!is_single() ) {
$posttitle = get_the_title( $postarr['post_parent'] );
$data['post_title'] = $posttitle;
$data['post_name'] = $posttitle;
return $data;
}}
add_filter( 'wp_insert_attachment_data', 'wpq_insert_attachment_data', 10, 2 );
It works superb but it covers all single/custom post type/pages etc. Is there any way to EXCLUDE pages from that function? I've tried sorting it out with is_single() yet without success.
Use is_singular in your statement to target specific post types.
Can also do an array to include or exclude.
If (! is_singular()) ..... or.....
(! is_singular(array('page','food',foo')))
Then it will only run on the singles for whichever post type you're targeting.
Looks like you just need to tweak your conditional statement:
if (!is_single() ) {
Should become:
if (!is_page() ) {
Load the function only on specific page, add your page id in is_page(id_here) :
function wpq_insert_attachment_data($data, $postarr){
if ( is_page(page_id)){
$posttitle = get_the_title( $postarr['post_parent'] );
$data['post_title'] = $posttitle;
$data['post_name'] = $posttitle;
return $data;
}
}
add_filter( 'wp_insert_attachment_data', 'wpq_insert_attachment_data', 10, 2 );
you can also add your page slug instead of id like :
if ( is_page('slug'))
Or exclude page(s)
if ( !is_page('slug'))
if ( !is_page(array('slug-1', 'slug-2') )
I have a class sitting in my Wordpress functions.php. Eventually it's going to end up in the plugins folder but one step at a time. Below is a foreshortened version of it:
class metaboxClass {
$them_meta_boxes = array (
array (
"1a_myplugin_box_id_1",
"1b_Custom Meta Box Title 1"
),
array (
"2a_myplugin_box_id_2",
"2b_Custom Meta Box Title 2"
)
);
public function __construct() {
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
}
public function add_meta_box( $post_type ) {
$post_types = array( 'page', 'my_cpt' );
if ( in_array( $post_type, $post_types )) { // *** IF $POST_TYPE IS IN THE ARRAY $POST_TYPES
foreach ($this->them_meta_boxes as $level_1) {
add_meta_box (
foreach ($this->level_1 as $level_2) {
echo $level_1 . ",";
}
array( $this, 'render_form'),
$post_type
)
}
}
}
}
As you can see from the above, I'm trying to construct various iterations of the add_meta_boxes function using the information in the array.
I've a feeling that there are a number of issues here and I'm kind of going through them one at a time but the first is that when an object is instantiated from the class I get: "syntax error, unexpected 'foreach' ". I know this is usually caused by a missing semi-colon. In this case the semi colon is present and correct. I've a feeling it's something to do with the placement of the array but I'm getting similar problems when it's placed outside. Can anyone give me any pointers - I'm pretty new to the world of OO PHP and also to really getting my hands dirty with the wordpress backend so any pointers would be appreciated.
Thanks in advance,
Stef
You can't pass a foreach loop as a parameter to a function. Construct your argument string first and then pass the constructed string as an argument to your add_meta_box function.
Even then though, I'm not sure what you are trying to call since your add_meta_box function only takes one argument.
Got it sorted for the record... ended up something like this:
class initialise_meta_boxes {
public $meta_boxes_array = array (
array (
"1a_myplugin_box_id_1",
"1b_Custom Meta Box Title 1",
"render_dropdown"
),
array (
"2a_myplugin_box_id_2",
"2b_Custom Meta Box Title 2",
"render_dropdown"
)
);
public function __construct() {
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
add_action( 'save_post', array( $this, 'save' ) );
}
public function make_meta_box($meta_id, $meta_title, $meta_callback) {
return add_meta_box ($meta_id, $meta_title, $meta_callback, $post_type );
}
public function add_meta_box( $post_type ) { // *** $post_type is global variable!!!
$post_types = array( 'page', 'my_cpt' );
if ( in_array( $post_type, $post_types )) { // *** IF $POST_TYPE IS IN THE ARRAY $POST_TYPES
foreach ($this->meta_boxes_array as $value) {
$this->make_meta_box($value[0], $value[1], array( $this, $value[2]));
}
}
}
}
I have a syntax error in my php code and just cannot figure out how should I fix it. I've been trying for ages and narrowed down the faulty code to the following :
<?php
global $post;
$tax_classes = array_filter( array_map( 'trim', explode( "\n", get_option( 'woocommerce_tax_classes' ) ) ) );
if ( ! class_exists( 'Tax_Meta_Boxes' ) ) :
class Tax_Meta_Boxes {
public function __construct() {
add_action( 'save_post', array( $this, 'tax_meta_data' ) );
}
}
?>
I ran the code through the PHP checker, the error seems to be with the last line and ?>.
I tried fiddling around with it, remove it, but error still there.
The error is caused by the function :
if ( ! class_exists( 'Tax_Meta_Boxes' ) ) :
class Tax_Meta_Boxes {
public function __construct() {
add_action( 'save_post', array( $this, 'tax_meta_data' ) );
}
}
If I remove the function, my error is gone, but what is wrong in the code of this function, how can I fix it ?
You have missed endif; for your if()
<?php
global $post;
$tax_classes = array_filter( array_map( 'trim', explode( "\n", get_option( 'woocommerce_tax_classes' ) ) ) );
if ( ! class_exists( 'Tax_Meta_Boxes' ) ) :
class Tax_Meta_Boxes {
public function __construct() {
add_action( 'save_post', array( $this, 'tax_meta_data' ) );
}
}
endif;// this line
?>