I am trying to hide specific shopping rates during the weekdays and offer them only on weekend (friday evening to be exact). I have 5 rates, I would like to show first 3 (by id ) always and rate 4 and 5 only on friday afternoon and night.
add_filter( 'woocommerce_package_rates', 'hide_friday_special_shipping_method', 10, 2 );
function hide_friday_special_shipping_method ( $rates, $package ) {
if ( date("N")==5 && date("G")>=15 || date("N")==6 && date("G")<=8) {
foreach ( $rates as $rate_id => $rate ) {
if ( '5' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
= array();
}
foreach ( $rates as $rate_id => $rate ) {
if ( '4' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
break;
}
}
return ! empty( $free ) ? $free : $rates;
= array();
}
return $rates;
}
It doesnt return anything. Could you please advice me on what should i do ?
function hide_friday_special_shipping_method ( $rates ) {
if ( date("N")==4 && date("G")>=1 || date("N")==6 && date("G")<=8) {
$rates = unset($rates[3]);
$rates = unset($rates[4]);
}
return $rates;
}
print_r($rates);
Tried this but it doesnt work either..
Related
I'm using Free Product Sample for the WooCommerce plugin and trying to set conditional free shipping only for a Sample product, sample product cost is 0 and therefore I'm trying to hide free shipping unless the order subtotal amount is 0.
To put it in a nutshell:
I want to offer free shipping only for sample products and, the free shipping method should only visible for a product having subtotal = 0
Screenshot for further clarification:
My attempted code:
function ts_hide_shipping_for_order_total( $rates ) {
$rate = array();
$order_total = WC()->cart->get_subtotal();
if( $order_total > 0 ) {
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping:20' === $rate->get_method_id() ) {
$rate[ $rate_id ] = $rate;
}
}
}
return ! empty( $free ) ? $free : $rates;
}
add_filter( 'woocommerce_package_rates', 'ts_hide_shipping_for_order_total', 100 );
OR
add_filter( 'woocommerce_package_rates', 'hide_shipping_except_local_when_free_is_available', 100 );
function hide_shipping_except_local_when_free_is_available($rates) {
$free = $local = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping:20' === $rate->method_id ) {
$free[ $rate_id ] = $rate;
}
}
return ! empty( $free ) ? array_merge( $free, $local ) : $rates;
}
But both codes do not give me the desired result. Can anyone point me in the right direction?
To hide/unset the "free shipping", as long as the subtotal is greater than 0, you can use the following.
So you get:
function filter_woocommerce_package_rates( $rates, $package ) {
// Get subtotal
$subtotal = $package['cart_subtotal'];
// Hide free shipping if subtotal > 0
if ( $subtotal > 0 ) {
// Loop trough
foreach ( $rates as $rate_id => $rate ) {
if ( $rate->method_id === 'free_shipping' ) {
unset( $rates[$rate_id] );
}
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );
Additional question: Hide the other methods when subtotal <= 0
function filter_woocommerce_package_rates( $rates, $package ) {
// Get subtotal
$subtotal = $package['cart_subtotal'];
// Loop trough
foreach ( $rates as $rate_id => $rate ) {
if ( $rate->method_id === 'free_shipping' ) {
// Hide free shipping if subtotal > 0
if ( $subtotal > 0 ) {
unset( $rates[$rate_id] );
}
} else {
// Hide other methods when subtotal <= 0
if ( $subtotal <= 0 ) {
unset( $rates[$rate_id] );
}
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );
I am trying to show only limited countries in WooComerce checkout for particular products only.
I am successfully able to get the cart product id but i cannot get it outside the function.
// hide countries
function get_cart_product_id() {
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
if(!empty($product)){
$live_pro = $product->get_id();
}
}
return $live_pro;
global $live_pro;
}
global $live_pro;
echo $live_pro; // Donesn't echo anything here. Below if also not working
if ($live_pro == 435925 || $live_pro == 435929 || $live_pro == 435930 || $live_pro == 435931 || $live_pro == 435932 ) {
add_filter( 'woocommerce_countries', 'bbloomer_custom_woocommerce_countries' );
}
function bbloomer_custom_woocommerce_countries( $country ) {
$country = array(
'ES' => 'Spain',
'PT' => 'Portugal',
'FR' => 'France',
);
return $country;
}
Any advice to help me find the solution?
To show/hide certain countries on WooCommerce checkout for particular products in cart, you can use the woocommerce_countries_allowed_countries filter hook.
Either you indicate which country (codes) you want to remove:
function filter_woocommerce_countries_allowed_countries( $countries ) {
// Cart or checkout page
if ( is_cart() || is_checkout() ) {
// The targeted product ids
$targeted_ids = array( 30, 815 );
// Flag
$found = false;
if ( WC()->cart ) {
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( array_intersect( $targeted_ids, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
$found = true;
break;
}
}
}
// True
if ( $found ) {
// Remove
unset( $countries[ 'NL' ] );
unset( $countries[ 'FR' ] );
}
}
// Return
return $countries;
}
add_filter( 'woocommerce_countries_allowed_countries', 'filter_woocommerce_countries_allowed_countries', 10, 1 );
OR
The reverse, and indicate which country (codes) you want to keep
function filter_woocommerce_countries_allowed_countries( $countries ) {
// Cart or checkout page
if ( is_cart() || is_checkout() ) {
// The targeted product ids
$targeted_ids = array( 30, 815 );
// Country codes you want to show
$show_countries = array( 'BE', 'NL', 'FR', 'ES' );
// Flag
$found = false;
if ( WC()->cart ) {
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( array_intersect( $targeted_ids, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
$found = true;
break;
}
}
}
// True
if ( $found ) {
// Loop through country codes
foreach ( $countries as $key => $country ) {
// NOT found
if ( ! in_array( $key, $show_countries ) ) {
// Remove
unset( $countries[$key] );
}
}
}
}
// Return
return $countries;
}
add_filter( 'woocommerce_countries_allowed_countries', 'filter_woocommerce_countries_allowed_countries', 10, 1 );
I need to disable certain payment methods based on the shipping class of items added in cart.
I have tried the following code:
add_filter( 'woocommerce_available_payment_gateways', 'unset_gateway_by_sclass' );
function unset_gateway_by_sclass( $available_gateways ) {
if ( is_admin() ) return $available_gateways;
$unset = false;
$category_ids = array( no-cod );
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
$terms = get_the_terms( $values['product_id'], 'shipping_class' );
foreach ( $terms as $term ) {
if ( in_array( $term->term_id, $category_ids ) ) {
$unset = true;
break;
}
}
}
if ( $unset == true ) unset( $available_gateways['cod'] );
return $available_gateways;
}
This is not working, where am I going wrong in this?
Figured it out
add_filter( 'woocommerce_available_payment_gateways', 'sclass_func', 10, 2 );
function sclass_func( $available_gateways ) {
$shipping_class_target = 1157;
$in_cart = false;
foreach( WC()->cart->cart_contents as $key => $values ) {
if( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target ) {
$in_cart = true;
break;
}
}
if( $in_cart ) {
unset($available_gateways['cod']);
}
return $available_gateways;
}
I am trying to learn some more advanced WordPress, I have used and adapted a code snippet but cannot understand some of it's origins. The snippet is for WooCommerce and hides other shipping methods when 'free shipping' is available.
It looks like a loop using a variable called $rates but I can't find anything in the Woo Dev Docs about this variable. I thought it may have been an instance of a class but again can't find any info that may help. Based on the snippet below, could someone tell me where $rates has originated from, what it is and where it would have been declared please?
add_filter( 'woocommerce_package_rates', 'bbloomer_unset_shipping_when_free_is_available_all_zones', 10, 2 );
function bbloomer_unset_shipping_when_free_is_available_all_zones( $rates, $package ) {
$all_free_rates = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
$all_free_rates[ $rate_id ] = $rate;
break;
}
}
if ( empty( $all_free_rates )) {
return $rates;
} else {
return $all_free_rates;
}
}
$rates is generated from function calculate_shipping_for_package() inside woocommerce/includes/class-wc-shipping.php. You can see the filter woocommerce_package_rates in below function
public function calculate_shipping_for_package( $package = array(), $package_key = 0 ) {
// If shipping is disabled or the package is invalid, return false.
if ( ! $this->enabled || empty( $package ) ) {
return false;
}
$package['rates'] = array();
// If the package is not shippable, e.g. trying to ship to an invalid country, do not calculate rates.
if ( $this->is_package_shippable( $package ) ) {
// Check if we need to recalculate shipping for this package.
$package_to_hash = $package;
// Remove data objects so hashes are consistent.
foreach ( $package_to_hash['contents'] as $item_id => $item ) {
unset( $package_to_hash['contents'][ $item_id ]['data'] );
}
$package_hash = 'wc_ship_' . md5( wp_json_encode( $package_to_hash ) . WC_Cache_Helper::get_transient_version( 'shipping' ) );
$session_key = 'shipping_for_package_' . $package_key;
$stored_rates = WC()->session->get( $session_key );
if ( ! is_array( $stored_rates ) || $package_hash !== $stored_rates['package_hash'] || 'yes' === get_option( 'woocommerce_shipping_debug_mode', 'no' ) ) {
foreach ( $this->load_shipping_methods( $package ) as $shipping_method ) {
if ( ! $shipping_method->supports( 'shipping-zones' ) || $shipping_method->get_instance_id() ) {
$package['rates'] = $package['rates'] + $shipping_method->get_rates_for_package( $package ); // + instead of array_merge maintains numeric keys
}
}
// Filter the calculated rates.
$package['rates'] = apply_filters( 'woocommerce_package_rates', $package['rates'], $package );
// Store in session to avoid recalculation.
WC()->session->set(
$session_key, array(
'package_hash' => $package_hash,
'rates' => $package['rates'],
)
);
} else {
$package['rates'] = $stored_rates['rates'];
}
}
return $package;
}
I need to create custom coupon type. Because i had custom calculation for custom coupon. Anyone out there help me.
Coupon calculation:
the cart has one product and value is 5000, then custom coupon code applied. The cart total need to change 2000. Similarly the cart has 2 product and value is 7000. If the custom coupon code applied, then cart total need to be 4000.
So the coupon need to make the cart total as flat 2000 for one product
In newer versions of WooCommerce, you will need to
Register a custom coupon type
Validate the coupon
Calculate & Apply the discount
Register custom coupon type
add_filter( 'woocommerce_coupon_discount_types', 'custom_coupon_type',10, 1);
function custom_coupon_type( $discount_types ) {
$discount_types['my_type'] =__( 'My New Coupon Type', 'woocommerce' );
return $discount_types;
}
Validate the coupon
add_filter('woocommerce_coupon_is_valid_for_product', 'validate_custom_coupon', 10, 4);
function validate_custom_coupon($valid, $product, $coupon, $values){
if ( ! $coupon->is_type( array( 'my_type' ) ) ) {
return $valid;
}
$product_cats = wp_get_post_terms( $product->id, 'product_cat', array( "fields" => "ids" ) );
// SPECIFIC PRODUCTS ARE DISCOUNTED
if ( sizeof( $coupon->product_ids ) > 0 ) {
if ( in_array( $product->id, $coupon->product_ids ) || ( isset( $product->variation_id ) && in_array( $product->variation_id, $coupon->product_ids ) ) || in_array( $product->get_parent(), $coupon->product_ids ) ) {
$valid = true;
}
}
// CATEGORY DISCOUNTS
if ( sizeof( $coupon->product_categories ) > 0 ) {
if ( sizeof( array_intersect( $product_cats, $coupon->product_categories ) ) > 0 ) {
$valid = true;
}
}
// IF ALL ITEMS ARE DISCOUNTED
if ( ! sizeof( $coupon->product_ids ) && ! sizeof( $coupon->product_categories ) ) {
$valid = true;
}
// SPECIFIC PRODUCT IDs EXLCUDED FROM DISCOUNT
if ( sizeof( $coupon->exclude_product_ids ) > 0 ) {
if ( in_array( $product->id, $coupon->exclude_product_ids ) || ( isset( $product->variation_id ) && in_array( $product->variation_id, $coupon->exclude_product_ids ) ) || in_array( $product->get_parent(), $coupon->exclude_product_ids ) ) {
$valid = false;
}
}
// SPECIFIC CATEGORIES EXLCUDED FROM THE DISCOUNT
if ( sizeof( $coupon->exclude_product_categories ) > 0 ) {
if ( sizeof( array_intersect( $product_cats, $coupon->exclude_product_categories ) ) > 0 ) {
$valid = false;
}
}
// SALE ITEMS EXCLUDED FROM DISCOUNT
if ( $coupon->exclude_sale_items == 'yes' ) {
$product_ids_on_sale = wc_get_product_ids_on_sale();
if ( isset( $product->variation_id ) ) {
if ( in_array( $product->variation_id, $product_ids_on_sale, true ) ) {
$valid = false;
}
} elseif ( in_array( $product->id, $product_ids_on_sale, true ) ) {
$valid = false;
}
}
return $valid;
}
Calculate & Apply Discount
add_filter('woocommerce_coupon_get_discount_amount', 'wc_cpn_disc', 10, 5);
function wc_cpn_disc($discount, $discounting_amount, $cart_item, $single, $coupon) {
// IF TYPE MATCHES PERFORM CUSTOM CALCULATION
if ($coupon->type == 'my_type')
$discount = $cart_item['quantity'] * 2000;
return $discount;
}
Sources:
#raju_odi's answer on this exact question
#Chris Morris's answer to Woocommerce custom coupon type with custom discount always return 0
Please use below code in your active theme's function.php
function custom_discount_type( $discount_types ) {
$discount_types['custom_discount'] =__( 'custom discount', 'woocommerce' );
return $discount_types;
}
// add the hooks
add_filter( 'woocommerce_coupon_discount_types', 'custom_discount_type',10, 1);
//function to get coupon amount for "custom_discount"
function woocommerce_coupon_get_discount_amount($discount, $discounting_amount, $cart_item, $single, $coupon) {
if ($coupon->code == 'custom'){
//echo "yes custom discount"; //if $coupon->type == 'fixed_cart' or 'percent' or 'fixed_product' or 'percent_product' The code Works
$discount = $cart_item['quantity'] * 2000;
return $discount;
} else {
return $discount;
}
}
//add hook to coupon amount hook
add_filter('woocommerce_coupon_get_discount_amount', 'woocommerce_coupon_get_discount_amount', 10, 5);
Note : Please add your added coupon name here on this line if ($coupon->code == 'your_added_coupon_here')
Working fine and tested.