I am trying to rewrite the following in order to check for logged in user (instead of wholesale customers). I have the following, who can help me edit it so that it works? The original code can be found here.
add_filter( 'woocommerce_package_rates', 'shipping_methods_based_on_logged_in', 10, 2 );
function shipping_methods_based_on_logged_in( $rates, $package ){
$usermeta = get_user_meta( get_current_user_id() ,'wp_capabilities' ,true );
// Set the shipping methods rate ids in the arrays:
if ($login->isUserLoggedIn() == true) {
$shipping_rates_ids = array('flat_rate:10', 'flat_rate:7'); // To be removed for NON Wholesale users
} else {
$shipping_rates_ids = array('flat_rate:13', 'flat_rate:15'); // To be removed for Wholesale users
}
// Loop through shipping rates from the current shipping package
foreach( $rates as $rate_key => $rate ) {
if ( in_array( $rate_key, $shipping_rates_ids) ) {
unset( $rates[$rate_key] );
}
}
return $rates;
}
You need to check if is_user_logged_in()
add_filter( 'woocommerce_package_rates', 'shipping_methods_based_on_wholesale_customer', 10, 2 );
function shipping_methods_based_on_wholesale_customer( $rates, $package ) {
// Set the shipping methods rate ids in the arrays.
if ( ! is_user_logged_in() ) { // If user is NOT logged in.
$shipping_rates_ids = array( 'flat_rate:10', 'flat_rate:7' ); // To be removed for NON Wholesale users.
} else {
$shipping_rates_ids = array( 'flat_rate:13', 'flat_rate:15' ); // To be removed for Wholesale users.
}
// Loop through shipping rates from the current shipping package.
foreach ( $rates as $rate_key => $rate ) {
if ( in_array( $rate_key, $shipping_rates_ids, true ) ) {
unset( $rates[ $rate_key ] );
}
}
return $rates;
}
Related
I'm working on hiding free shipping when there is a fixed price shipping amount based on certain products. This code is working and after certain sum is also disabled. But I want this to work with flat shipping conditional, not post class conditional.
I want it: if ( isset( $rates['flat_rate:1'] ) )
But it works: if ( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target )
add_filter( 'woocommerce_package_rates', 'bbloomer_hide_free_shipping_for_shipping_class', 9999, 2 );
function bbloomer_hide_free_shipping_for_shipping_class( $rates, $package ) {
$shipping_class_target = 261; // shipping class ID (to find it, see screenshot below)
$subtotal = WC()->cart->get_subtotal();
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target && $subtotal <= 299 ) {
$in_cart = true;
break;
}
}
if ( $in_cart ) {
unset( $rates['free_shipping:2'] ); // shipping method with ID (to find it, see screenshot below)
}
return $rates;
}
I use this to unset shipping for product with specific tag:
function specific_products_shipping_methods( $rates, $package ){
// etiquette cocolis
$terms = array( 'cocolis' );
$taxonomy = 'product_tag';
foreach( $package['contents'] as $cart_item ) {
if ( has_term( $terms, $taxonomy, $cart_item['product_id'] ) )
{
unset( $rates['oik_weight_zone_shipping_49'] );
unset( $rates['chrono10'] );
unset( $rates['chrono13'] );
add_filter('woocommerce_shipping_chosen_method', 'reset_default_shipping_method', 10, 2);
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'specific_products_shipping_methods', 10, 2 );
function reset_default_shipping_method( $method, $available_methods ) {
$default_method = 'per_product';
if( array_key_exists($method, $available_methods ) )
return $default_method;
else
return $method;
}
This works fine until update woo 4.8.0
Any idea what’s wrong ?
Thx,
There are some mistakes in your code, try the following revisited and optimized code instead:
add_filter( 'woocommerce_package_rates', 'specific_products_shipping_methods', 10, 2 );
function specific_products_shipping_methods( $rates, $package ){
$terms = array('cocolis'); // Array of term slugs, names or ids
$taxonomy = 'product_tag'; // WooCommerce product tag taxonomy
$rate_keys = array('oik_weight_zone_shipping_49', 'chrono10', 'chrono13'); // Shipping rates to be hidden
$has_unset = false; // Initializing
// Loop through cart items for the current shipping package
foreach( $package['contents'] as $cart_item ) {
// Targeting specific product tags
if ( has_term( $terms, $taxonomy, $cart_item['product_id'] ) ) {
// Loop through shipping rates to be removed (hidden)
foreach( $rate_keys as $rate_key ) {
if (isset($rates[$rate_key]) ) {
unset($rates[$rate_key]);
$has_unset = true; // Flag as unset to enable the filter below
}
}
}
}
if ( $has_unset ) {
add_filter('woocommerce_shipping_chosen_method', 'reset_default_shipping_method', 10, 3 );
}
return $rates;
}
function reset_default_shipping_method( $default, $rates, $chosen_method ) {
$targeted_method = 'per_product'; // The shipping method rate to set as chosen one
if( isset($rates[$targeted_method]) ) {
$default = $targeted_method;
}
return $default;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works in WooCommerce 4.8+.
Don't forget to empty your cart to refresh WooCommerce shipping caches
Note: For WooCommerce categories, define the $taxonomy variable to product_cat instead.
For Woocommerce, I need a PHP snippet that will hide few products ID's I will select for guests and customers.
My code attempt:
function dma_restrict_product() {
$user = wp_get_current_user();
$user_meta = get_userdata($user->ID);
$user_roles = $user_meta->roles;
global $product;
if( in_array( 'customer', (array) $user_roles ) && ( is_single('3759') ) ) {
return true;
add_filter('woocommerce_is_purchasable', 'woocommerce_cloudways_purchasable');
function woocommerce_cloudways_purchasable($cloudways_purchasable, $product) {
return ($product->id == 3759 ? false : $cloudways_purchasable);
}
} else if( in_array('administrator', (array) $user_roles) ) {
return true;
} else {
return false;
}
}
But it doesn't work as I would like.
If you want to hide the product completly:
You can hide products by using the ID of the product and exclude it from the product query:
function hide_my_product( $q ) {
$user = wp_get_current_user();
$user_meta = get_userdata($user->ID);
$user_roles = $user_meta->roles;
if ( !in_array( 'administrator', $user_roles ) ) {
// id of product to hide
$product_id = 3759;
// exclude the id from query
$q->set( 'post__not_in', $product_id );
}
}
add_action( 'woocommerce_product_query', 'hide_my_product' );
If you want to hide the add to cart button of product:
If you want to list the product with price, but only hide the "Add to Cart" button, you can do this with the woocommerce_is_purchasable hook, that will return false for your product ids and therefore will show the price, but in the place of "Add to Cart" button the notice "Product cannot be purchased" appears.
add_filter( 'woocommerce_is_purchasable', 'hide_add_to_cart_button', 10, 2 );
function hide_add_to_cart_button( $purchasable = true, $product ) {
$user = wp_get_current_user();
$user_meta = get_userdata($user->ID);
$user_roles = $user_meta->roles;
if ( !in_array( 'administrator', $user_roles ) && $product->get_id() == 3759 ) {
$purchasable = false;
}
return $purchasable;
}
There are 2 different request on your question (one in the title and another a bit different in the body):
1). To avoid guests and customers to purchase some defined products (hiding or disabling add to cart button), use the following:
add_filter( 'woocommerce_is_purchasable', 'restrict_purchases_on_defined_product', 10, 2 );
function restrict_purchases_on_defined_product( $is_purchasable, $product ) {
// For guest users or "customer" user role
if ( ! is_user_logged_in() || current_user_can( 'customer' ) ) {
// HERE define your product ID(s) that will noot be purchassable
$restricted_product_ids = array(37, 53, 70);
if ( array_intersect( array( $product->get_id(), $product->get_parent_id() ), $restricted_product_ids ) ) {
return false;
}
}
return $is_purchasable;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
2). To hide completely some defined products from guests and customers, use the following:
// Settings: HERE define your product ID(s) that will not be purchasable
function my_hidden_product_ids() {
return array(37, 53, 70);
}
// Hide some products from product loops
add_action( 'woocommerce_product_query', 'hide_defined_product' );
function hide_defined_product( $query ) {
// For guest users or "customer" user role
if ( ! is_user_logged_in() || current_user_can( 'customer' ) ) {
$hidden_product_ids = my_hidden_product_ids();
$query->set( 'post__not_in', $hidden_product_ids );
}
}
// Redirect some product pages to main shop page (for security)
add_action( 'template_redirect', 'redirect_defined_product_single_pages' );
function redirect_defined_product_single_pages( $query ) {
// For guest users or "customer" user role
if ( ! is_user_logged_in() || current_user_can( 'customer' ) ) {
$hidden_product_ids = my_hidden_product_ids();
if ( in_array( get_queried_object_id(), $hidden_product_ids ) ) {
wp_redirect( wc_get_page_permalink( 'shop' ) );
exit();
}
}
}
// Check and remove related cart items silently (for security)
add_action('woocommerce_before_calculate_totals', 'remove_specific_products_from_cart', 10, 1 );
function remove_specific_products_from_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// For guest users or "customer" user role
if ( ! is_user_logged_in() || current_user_can( 'customer' ) ) {
$hidden_product_ids = my_hidden_product_ids();
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
if ( array_intersect( array( $cart_item['product_id'], $cart_item['variation_id'] ), $hidden_product_ids ) ) {
$cart->remove_cart_item( $cart_item_key );
}
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Related: Hide a specific Woocommerce products from loop if they are in cart
I need to remove my UPS shipping methods on the cart and checkout pages after the cart weight surpasses 150lbs. This is along the lines of what I'm thinking...
function is_it_over_onefifty($available_methods){
global $woocommerce;
if ($woocommerce->cart->cart_contents_weight > 150){
//diable shipping
unset( $available_methods['ups'] );
}
else{
//do nothing
}
return $available_methods;
}
add_filter( 'woocommerce_available_shipping_methods', 'is_it_over_onefifty', 10, 1);
add_filter( 'woocommerce_package_rates', 'define_default_shipping_method', 10, 2 );
function define_default_shipping_method( $rates, $package ) {
// Only unset rates if free_shipping is available
if ( isset( $rates['free_shipping:8'] ) ) {
unset( $rates['flat_rate:4'] );
}
return $rates;
}
I had started with a comment, but it became too large.
Below is some solid example code that will get you going where you need to. Note the idea is taken from here: http://www.bolderelements.net/support/knowledgebase/hide-shipping-method-based-on-weight/
add_filter( 'woocommerce_package_rates', 'hide_shipping_weight_based', 10, 2 );
function hide_shipping_weight_based( $rates, $package ) {
// if you don't know what the rates are, you can uncomment below to see all the rates that are available
// var_dump( $rates );
// Set weight variable
$cart_weight = 0;
// Shipping rate to be excluded
$shipping_type = 'ups_';
// Calculate cart's total
foreach( WC()->cart->cart_contents as $key => $value) {
$cart_weight += $value['data']->weight * $value['quantity'];
}
// only if the weight is over 150lbs find / remove specific carrier
if( $cart_weight > 150 ) {
// loop through all of the available rates
foreach( $rates AS $id => $data ) {
// if the rate id starts with "ups_"
if ( 0 === stripos( $id, $shipping_type ) ) {
unset( $rates[ $id ] ); // remove it
}
}
}
return $rates;
}
I would like to disable all payments gateways under special situation: I've 2 special products that I don't want to be combined at checkout with any other product.
Lets say that my "special" products IDs are 496 and 484. All other are "normal" products.
if one of these "special" products is in the cart, I want to disable "paypal" for example.
if a customer has in his cart, at once, a "special" product and a "normal" product, I want to disable all the payments gateway, so he can't checkout.
This is my code:
//disable add to cart if
add_filter( 'woocommerce_available_payment_gateways', 'filter_gateways', 1);
function filter_gateways( $gateways )
{
global $woocommerce;
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
// store product IDs in array
$nonPPproducts = array(496,484);
if (in_array( $values['product_id'], $nonPPproducts ) ) {
unset($gateways['cod'], $gateways['bacs'], $gateways['cheque'], $gateways['stripe']);
} elseif ( in_array( $values['product_id'], $nonPPproducts ) && in_array( $values['product_id'] ) ) {
unset($gateways['under-review'], $gateways['cod'], $gateways['bacs'], $gateways['cheque'], $gateways['stripe']);
}
}
return $gateways;
}
But I can't figure out why the only first if statement works… In other words whatever the situation, all payment gateways are disabled except under-review payment gateway.
What I am doing wrong?
How can I achieve this?
Thanks
Updated for WooCommerce 3+
First I think that in_array( $values['product_id'] ) in your code is not working as a correct condition and so your else statement is never "true". Then as a customer can have many items in his cart, depending on customer successive choices, with your code there will be many redundant gateway unsets…
Here it is your code revisited (you will need to put the desire unset gateways in each statement):
add_filter( 'woocommerce_available_payment_gateways', 'filter_gateways', 1);
function filter_gateways( $gateways ){
// Not in backend (admin)
if( is_admin() )
return $gateways;
// Storing special product IDs in an array
$non_pp_products = array( 496, 484 );
// Needed variables
$is_non_prod = false;
$is_prod = false;
$count = 0;
foreach ( WC()->cart->get_cart() as $cart_item ) {
// count number of items if needed (optional)
$count++;
$product = $cart_item['data'];
if( ! empty($product) ){
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
if ( in_array( $product_id, $non_pp_products ) && ! $is_non_prod )
$is_non_prod = true;
if ( !in_array( $product_id, $non_pp_products ) && !$is_prod )
$is_prod = true;
}
}
if ( $is_non_prod && ! $is_prod ) // only special products
{
// unset only paypal;
unset( $gateways['paypal'] );
}
elseif ( $is_non_prod && $is_prod ) // special and normal products mixed
{
// unset ALL GATEWAYS
unset( $gateways['cod'],
$gateways['bacs'],
$gateways['cheque'],
$gateways['paypal'],
$gateways['stripe'],
$gateways['under-review'] );
}
elseif ( ! $is_non_prod && $is_prod ) // only normal products (optional)
{
// (unset something if needed)
}
return $gateways;
}
Naturally this code goes on functions.php file of your active child theme or theme.