I'm trying to remove all default bulk actions from the admin's orders page with the following code:
add_filter( 'bulk_actions-edit-shop_order', 'remove_order_statuses_bulk' );
function remove_order_statuses_bulk ( $bulk_actions ) {
error_log( print_r( $bulk_actions, true ) );
$unwanted_actions = array( "mark_processing", "mark_pending", "mark_on-hold", "mark_completed", "mark_cancelled", "mark_refunded", "mark_failed" );
foreach ( $unwanted_actions as $action ) {
if ( isset( $bulk_actions[$action] ) ) {
unset( $bulk_actions[$action] );
}
}
return $bulk_actions;
}
The error_log shows the array containing just "edit", "trash" and "mark_custom-status" (which is a status that I've created using the same hook). So the array is already empty.
The problem is that the menu with bulk actions in wp-admin/edit.php?post_type=shop_order is still showing the removed entries.
I have no caching plugin at present. What may be causing this?
Your function is being called too early since you don't have a priority set.
Change the priority of your add_filter and it works.
add_filter( 'bulk_actions-edit-shop_order', 'remove_order_statuses_bulk', 40, 1 );
Related
I am using the following function to automatically replace the product in the cart if the user adds another product. Its working perfectly.
I am trying to add a redirect to checkout after the product has been replaced. But the redirect does not work as I wish.
function custom_maybe_empty_cart( $valid, $product_id, $quantity ) {
if( ! empty ( WC()->cart->get_cart() ) && $valid ){
WC()->cart->empty_cart();
wc_add_notice( 'Only allowed 1 item in cart.', 'error' );
}
return $valid;
wp_redirect( 'https://ils.semarient.io/commander' );
exit;
}
add_filter( 'woocommerce_add_to_cart_validation', 'custom_maybe_empty_cart', 10, 3 );
I've tried different placements for the following lines :
wp_redirect( 'https://ils.semarient.io/commander' );
exit;
1 ) after the wc_add_notice : nothing happens
2 ) after teturn $valid : nothing happens
3 ) after final brace (before add filter) : endlessly loops to redirect to the page I want and ends in a page crash (too many redirects) > means the redirect is working then ? but isn't at the right place...
Code is in the function.php file from child theme
Thanks a lot for any help !
My initial problem is that AJAX add-to-cart button on Woocommerce doesn't seem to work on Private products (which we're only displaying to a selection of customers): the wheel appears on the add-to-cart button, the page reloads, and the product is added to cart but there's no notice that it has, so it's quite confusing.
After lots of research, all I could find is this thread https://wordpress.org/support/topic/add-to-cart-redirecting-only-on-private-products-2/ which led me to believe it's most likely a bug?
I tried to come up with a work-around: disable AJAX add-to-cart and revert to default behaviour on Private products only so we can still display some kind of notification that the product has been added to cart. I've thought of this code as a starting point:
add_action( 'wp_enqueue_scripts', 'bbloomer_disable_woocommerce_cart_fragments', 11 );
function bbloomer_disable_woocommerce_cart_fragments() {
if ( is_front_page() ) wp_dequeue_script( 'wc-cart-fragments' );
}
Would this work? And how would I modify it so the condition is "if is private product"?
You could solve the problem by thinking the other way around. Instead of showing private products only for specific users you could hide them for all other user roles (leaving the products with the "publish" status).
This way the Ajax problem does not arise.
If the user has one of the roles defined in the $user_roles array of the following function, it hides all products in the $product_ids_to_hide array:
// hide products based on user role
add_filter( 'woocommerce_product_is_visible', 'hide_products_by_user_role', 10, 2 );
function hide_products_by_user_role( $visible, $product_id ) {
// only if the user is logged in
if ( ! is_user_logged_in() ) {
return $visible;
}
// set the product ids to hide
$product_ids_to_hide = array( 12, 14 );
// sets the user roles for which products are to be hidden
$user_roles = array( 'custom_role_1', 'custom_role_2' );
$user = wp_get_current_user();
if ( array_intersect( $user_roles, $user->roles ) && in_array( $product_id, $product_ids_to_hide ) ) {
return false;
}
return $visible;
}
To reply to your comment:
If you want to allow the user to modify the product ids to be hidden based on the user role you can create a .csv file to be uploaded to FTP with the list of product ids, one per line.
If your client in the future wants to remove or add a product id, he can do so simply by overwriting the .csv file with an FTP import or directly in the file manager (if the hosting allows it).
The file I created as an example will be called product-ids-to-hide.csv and will need to be uploaded to the same directory as the functions.php file. No header is required. Here is an example:
349
235
456
745
and this will be the new updated function:
// hide products based on user role
add_filter( 'woocommerce_product_is_visible', 'hide_products_by_user_role', 10, 2 );
function hide_products_by_user_role( $visible, $product_id ) {
// only if the user is logged in
if ( ! is_user_logged_in() ) {
return $visible;
}
// sets the user roles for which products are to be hidden
$user_roles = array( 'custom_role_1', 'custom_role_2' );
$user = wp_get_current_user();
// only if the user has at least one role present in the array
if ( empty( array_intersect( $user_roles, $user->roles ) ) ) {
return $visible;
}
// get an array with product ids
$product_ids_to_hide = file( realpath( __DIR__ . '/product-ids-to-hide.csv' ), FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
if ( in_array( $product_id, $product_ids_to_hide ) ) {
return false;
}
return $visible;
}
The code has been tested and works. Add it to your active theme's functions.php.
So I have this chunk of PHP that excluded a certain element from appearing on all of my WordPress pages, while keeping them on posts/products, but there's a couple of pages where I would still like it to appear.
How do I go about excluding certain Page IDs from this query?
add_action( 'template_redirect', 'avada_check_page' );
function avada_check_page() {
if ( is_singular( 'page' ) ) {
add_action( 'avada_override_current_page_title_bar', 'avada_remove_title_bar' );
}
}
function avada_remove_title_bar() {
}
There's about 100 pages I want to apply this to and only 5 where I want to exclude them from this code.
A simple way would just be to use a condition on that first if statement.
add_action( 'template_redirect', 'avada_check_page' );
function avada_check_page() {
if ( is_singular( 'page' ) && !in_array(get_the_ID(),array(1,2,3,4)) ) {
add_action( 'avada_override_current_page_title_bar', 'avada_remove_title_bar' );
}
}
function avada_remove_title_bar() {
}
Where 1,2,3,4 place the exceptions posts ID's.
During the add_to_cart function, there is a filter to add "cart item data". The filter is woocommerce_add_cart_item_data. I expected to store my custom plugin data in this, so that the data is stored relative to the item and multiple products can be added with different data.
This all seemed to work, but I am not able to retrieve the data. I can't figure it out. The data is there, I can see it in a serialized string, but I can't pull it out.
echo '<pre>';
var_dump( WC() );
foreach( WC()->cart->get_cart() as $cart_item ) {
var_dump( $cart_item );
var_dump( WC()->cart->get_item_data( $cart_item ) );
}
echo '</pre>';
The first dump of WC() has a property: session->_data->cart->(serialized data). The _data property is protected, though, but I can see my custom field inside the serialized data.
The $cart_item is an array with product_id and some other data, but it does not include my custom data :(
Finally, using the get_item_data() method I thought I had it all figured out. I passed in the cart item object, and... an empty string. Same if I pass the key, rather than the cart item itself.
How am I supposed to access the cart item data?
Here is the "Add cart item data" function, which works (or at least seems to work):
function save_class_menu_selection( $cart_item_data, $product_id, $variation_id ) {
if ( !product_is_class( $product_id ) ) return $cart_item_data;
// Save the date, or give a fatal warning. Date is required.
if ( !empty($_REQUEST['class-date']) ) {
$cart_item_data['class-date'] = stripslashes($_REQUEST['class-date']);
return $cart_item_data;
}else{
wp_die('<h2>Invalid Class Date Selected</h2><p>You tried to add a class to your cart, but the date selected was invalid. Please try again.</p>');
exit;
}
}
add_filter( 'woocommerce_add_cart_item_data', 'save_class_menu_selection', 10, 3 );
I was in the same situation today and stumbled over this question after some research.
After some reverse engineering I found the problem and want to provide a solution for other which may also stumble over this question.
The problem is that the data gets sanitized when the cart items get restored from the session. So the extra cart item data IS stored into the session but on the next request it does not get restored.
There is a filter "woocommerce_get_cart_item_from_session". As first parameter you get the sanitized cart item (without extra data) and as second all data which got stored into the session (including extra data).
The solution is to hook in there and also restore your custom cart item data.
Example Code:
add_filter( 'woocommerce_add_cart_item_data', function ( $cartItemData, $productId, $variationId ) {
$cartItemData['myCustomData'] = 'someCustomValue';
return $cartItemData;
}, 10, 3 );
add_filter( 'woocommerce_get_cart_item_from_session', function ( $cartItemData, $cartItemSessionData, $cartItemKey ) {
if ( isset( $cartItemSessionData['myCustomData'] ) ) {
$cartItemData['myCustomData'] = $cartItemSessionData['myCustomData'];
}
return $cartItemData;
}, 10, 3 );
To also show the data at the cart/checkout page you can use the following code:
add_filter( 'woocommerce_get_item_data', function ( $data, $cartItem ) {
if ( isset( $cartItem['myCustomData'] ) ) {
$data[] = array(
'name' => 'My custom data',
'value' => $cartItem['myCustomData']
);
}
return $data;
}, 10, 2 );
The final thing now is to save the data when the order is made:
add_action( 'woocommerce_add_order_item_meta', function ( $itemId, $values, $key ) {
if ( isset( $values['myCustomData'] ) ) {
wc_add_order_item_meta( $itemId, 'myCustomData', $values['myCustomData'] );
}
}, 10, 3 );
You dont have to do anything else the show the data inside the backend, all order item meta data gets display automatically.
I could not get the default cart item data to work, unfortunately. I feel it may not be properly implemented, or may even be deprecated, as there is a lack of support and documentation.
Instead, I used a cart session variable to accomplish the same thing. It's simply an array where each key is the cart_item_key. The value of each array is yet another array, containing a key-value pair of custom fields. So it's essentially the same thing as the built-in cart item data, except stored as cart session data instead.
Here is a Gist containing some utility functions to make it easy:
https://gist.github.com/RadGH/e3444fc661554a0f8c6f
Or if you want to build it yourself, the magic is in WC()->session. Here are the two key functions for this to work:
WC()->session->get('_my_cart_item_data');
WC()->session->set('_my_cart_item_data', $cart_item_data_array);
These are the action hooks you will need:
<<<EXAMPLES
action: woocommerce_add_to_cart
desc: When an item is added to the cart.
args: $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data
action: woocommerce_add_order_item_meta
desc: When a cart item is converted to an order item, save metadata to the order item
using the function "wc_add_order_item_meta( $item_id, $key, $value )"
args: item_id, $values, $cart_item_key
I have created a plugin mainly following this guide, which simply adds a small bit of data to a given product.
I know Woocommerce have made some changes outlined here.
The problem I'm having is that when I add my item to the cart, and access the cart page, I am getting a blank screen. I believe the problem stems from the use of this filter:
add_filter('woocommerce_get_cart_item_from_session'...
If I comment the line with this filter, my checkout page works (but without the extra details added to my product). I can't work out why this filter is not working, or what problem it is having??
The woocommerce changes said:
WooCommerce 2.0 no longer uses the PHP session_start function, instead it makes use of WordPress’ transients, which is great, unless your code happens to rely on $_SESSION.
I'm not starting any new sessions as far as I can see (my code is 90% the same as the first link). Maybe this is a problem with my server? Any ideas?
i was browsing a lot and i recommend that you read the following:
The solution is to hook in there and also restore your custom cart item data.
Example Code:
add_filter( 'woocommerce_add_cart_item_data', function ( $cartItemData, $productId, $variationId ) {
$cartItemData['myCustomData'] = 'someCustomValue';
return $cartItemData;
}, 10, 3 );
add_filter( 'woocommerce_get_cart_item_from_session', function ( $cartItemData, $cartItemSessionData, $cartItemKey ) {
if ( isset( $cartItemSessionData['myCustomData'] ) ) {
$cartItemData['myCustomData'] = $cartItemSessionData['myCustomData'];
}
return $cartItemData;
}, 10, 3 );
To also show the data at the cart/checkout page you can use the following code:
add_filter( 'woocommerce_get_item_data', function ( $data, $cartItem ) {
if ( isset( $cartItem['myCustomData'] ) ) {
$data[] = array(
'name' => 'My custom data',
'value' => $cartItem['myCustomData']
);
}
return $data;
}, 10, 2 );
The final thing now is to save the data when the order is made:
add_action( 'woocommerce_add_order_item_meta', function ( $itemId, $values, $key ) {
if ( isset( $values['myCustomData'] ) ) {
wc_add_order_item_meta( $itemId, 'myCustomData', $values['myCustomData'] );
}
}, 10, 3 );
You dont have to do anything else the show the data inside the backend, all order item meta data gets display automatically.
this is from
How to retrieve cart_item_data with WooCommerce?
you have to add this stuff to the functions.php file of your theme for example.