In Woocommerce I am using woocommerce_product_get_price like to alter my product prices and it is working fine… But when I add to cart a product, the cart total and cart item are zero.
That is my code:
add_filter( 'woocommerce_add_cart_item', 'set_custom_cart_item_prices', 20, 2 );
function set_custom_cart_item_prices( $cart_data, $cart_item_key ) {
$new_price = $cart_data['data']->get_price() * 2;
$cart_data['data']->set_price( $new_price );
$cart_data['new_price'] = $new_price;
return $cart_data;
}
add_filter( 'woocommerce_get_cart_item_from_session', 'set_custom_cart_item_prices_from_session', 20, 3 );
function set_custom_cart_item_prices_from_session( $session_data, $values, $key ) {
if ( ! isset( $session_data['new_price'] ) || empty ( $session_data['new_price'] ) )
return $session_data;
$session_data['data']->set_price( $session_data['new_price'] );
return $session_data;
}
Its doesn't work. I have also tried to use woocommerce_before_calculate_totals without success
How to avoid zero prices on cart? Any help is appreciated.
Updated: You are not using the correct hooks and the correct way. The following will replace all your code. The price changes will be done on simple products, variable products and product variations.
The 1st function is the rate to be applied to your product prices (so you will define in it your rate calculation).
The 2nd function will change all products displayed price on all product pages instead of using your custom function hooked in woocommerce_product_get_price filter hook.
The 3rd Function will change the products price in cart items, on cart and checkout pages and in orders items too.
// The price rate to be applied
function get_product_price_rate() {
// HERE define the price rate to be applied
return 1.25; // +25%
}
// Change the product displayed price on product pages
add_filter( 'woocommerce_get_price_html', 'custom_price_html', 10, 2 );
function custom_price_html( $price, $product ){
$rate = get_product_price_rate();
// Simple products and product variations
if( in_array( $product->get_type() , array( 'simple' , 'variation' ) ) ) {
$regular_price = wc_get_price_to_display( $product, array( 'price' => ( $product->get_regular_price() * $rate ) ) );
$active_price = wc_get_price_to_display( $product, array( 'price' => ( $product->get_price() * $rate ) ) );
if ( '' === $product->get_price() ) {
$price = apply_filters( 'woocommerce_empty_price_html', '', $product );
} elseif ( $product->is_on_sale() ) {
$price = wc_format_sale_price( $regular_price, $active_price ) . $product->get_price_suffix();
} else {
$price = wc_price( $active_price ) . $product->get_price_suffix();
}
}
// Variable products
elseif ( 'variable' === $product->get_type() ) {
$prices = $product->get_variation_prices( true );
if ( empty( $prices['price'] ) ) {
$price = apply_filters( 'woocommerce_variable_empty_price_html', '', $this );
} else {
$min_price = current( $prices['price'] ) * $rate;
$max_price = end( $prices['price'] ) * $rate;
$min_reg_price = current( $prices['regular_price'] ) * $rate;
$max_reg_price = end( $prices['regular_price'] ) * $rate;
if ( $min_price !== $max_price ) {
$price = wc_format_price_range( $min_price, $max_price );
} elseif ( $this->is_on_sale() && $min_reg_price === $max_reg_price ) {
$price = wc_format_sale_price( wc_price( $max_reg_price ), wc_price( $min_price ) );
} else {
$price = wc_price( $min_price );
}
$price .= $product->get_price_suffix();
}
}
return $price;
}
// Change cart items prices (and order items prices)
add_action('woocommerce_before_calculate_totals', 'increase_cart_item_prices', 100, 1 );
function increase_cart_item_prices( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop Through cart items
foreach ( $cart->get_cart() as $cart_item ) {
$rate = get_product_price_rate();
$cart_item['data']->set_price( $cart_item['data']->get_price() * $rate );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Related
For an upcoming sale, we have our existing registered customers will have a 'pre-order'. So they can avail of the sale prices they must be logged in. These prices need to be displayed anywhere where a product is displayed.
For logged-in customers I need to display both the regular price (slashed out) and the sale price otherwise guess. Plus I need to do this for both variable and simple products.
At the moment I have this code (Enable sale price for logged users and regular price for unlogged users in Woocommerce )
// Variable and simple product displayed prices (removing sale price range)
add_filter( 'woocommerce_get_price_html', 'custom_get_price_html', 20, 2 );
function custom_get_price_html( $price, $product ) {
if( $product->is_type('variable') )
{
if( is_user_logged_in() ){
$price_min = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_sale_price('min') ) );
$price_max = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_sale_price('max') ) );
} else {
$price_min = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_regular_price('min') ) );
$price_max = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_regular_price('max') ) );
}
if( $price_min != $price_max ){
if( $price_min == 0 && $price_max > 0 )
$price = wc_price( $price_max );
elseif( $price_min > 0 && $price_max == 0 )
$price = wc_price( $price_min );
else
$price = wc_format_price_range( $price_min, $price_max );
} else {
if( $price_min > 0 )
$price = wc_price( $price_min);
}
}
elseif( $product->is_type('simple') )
{
if( is_user_logged_in() ) {
$active_price = wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) );
} else {
$active_price = wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) );
}
if ( $active_price > 0 )
$price = wc_price($active_price);
}
return $price;
}
// Product Variation displayed prices
add_filter( 'woocommerce_available_variation', 'custom_variation_price', 10, 3);
function custom_variation_price( $data, $product, $variation ) {
$reg_price = wc_get_price_to_display( $variation, array( 'price' => $variation->get_regular_price() ) );
$sale_price = wc_get_price_to_display( $variation, array( 'price' => $variation->get_sale_price() ) ) ;
if( is_user_logged_in() )
$data['price_html'] = wc_price( $sale_price );
else
$data['price_html'] = wc_price( $reg_price );
return $data;
}
// Set the correct prices in cart
add_action( 'woocommerce_before_calculate_totals', 'set_item_cart_prices', 20, 1 );
function set_item_cart_prices( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ){
if( ! is_user_logged_in() ){
$cart_item['data']->set_price( $cart_item['data']->get_regular_price() );
}
}
}
It works but it only displays for logged customers the sale price and I need both regular and sale prices. I can see how the two different prices are determined depending on if the customer is logged in or not but I can't scale it to my needs. Could someone help me please, my PHP isn't up to scratch?
Many thanks.
You should try this:
add_action( 'init', 'woo_hide_price_add_cart_not_logged_in' );
function woo_hide_price_add_cart_not_logged_in() {
if ( ! is_user_logged_in() ) {
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_price', 10 );
remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
add_action( 'woocommerce_single_product_summary', 'woo_print_login_to_see', 31 );
add_action( 'woocommerce_after_shop_loop_item', 'woo_print_login_to_see', 11 );
}
}
function woo_print_login_to_see() {
global $product;
//echo '' . __('Login to see prices', 'theme_name') . '';
//$price = get_post_meta( get_the_ID(), '_regular_price', true);
//$price_sale = get_post_meta( get_the_ID(), '_sale_price', true);
if( $product->is_on_sale() ) {
// echo $product->get_sale_price();
}
echo $product->get_regular_price();
}
I want to display a custom currency symbol based on product category. I took the following snippet suggested on this question Change currency symbol based on product category in Woocommerce.
However I actually need the custom currency to be displayed also in all Woocommerce pages (including cart and checkout page).
This is my code:
add_filter('woocommerce_currency_symbol', 'change_existing_currency_symbol', 10, 2);
function change_existing_currency_symbol( $currency_symbol, $currency ) {
global $post, $product, $woocommerce;
if ( has_term( 'cupones', 'product_cat' ) ) :
switch( $currency ) {
case 'EUR': $currency_symbol = 'ptos'; break;
}
return $currency_symbol;
elseif ( has_term( 'cupones', 'product_cat' ) && is_cart() ):
switch( $currency ) {
case 'EUR': $currency_symbol = 'ptos'; break;
}
return $currency_symbol;
elseif ( has_term( 'cupones', 'product_cat' ) && is_checkout() ):
switch( $currency ) {
case 'EUR': $currency_symbol = 'ptos'; break;
}
return $currency_symbol;
endif;
}
Updated: For cart and checkout pages, there is 2 ways: By item or globally.
1) BY ITEM (The most complicated):
// HERE below your settings
function custom_currency_symbol_settings(){
return array(
'curr_symbol' => 'ptos', // <=== HERE define your currency symbol replacement
'currency' => 'EUR', // <=== HERE define the targeted currency code
'category' => array('cupones'), // <=== HERE define your product category(ies)
'taxonomy' => 'product_cat',
);
}
// On product pages - Custom currency symbol
add_filter( 'woocommerce_currency_symbol', 'change_existing_currency_symbol', 10, 2 );
function change_existing_currency_symbol( $currency_symbol, $currency ) {
global $post, $product;
// Loading your settings
$data = custom_currency_symbol_settings();
// Others Woocommerce product pages
if ( has_term( $data['category'], $data['taxonomy'] ) && $currency == $data['currency'] ) {
return $data['curr_symbol'];
}
return $currency_symbol;
}
// On cart item product price (Cart page) - Custom currency symbol
add_filter( 'woocommerce_cart_product_price', 'change_cart_item_price_currency_symbol', 10, 2 );
function change_cart_item_price_currency_symbol( $product_price_html, $product ) {
// Loading your settings
$data = custom_currency_symbol_settings();
// Get the correct product ID
$product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
// Only for the defined product category and the defined currency
if ( ! has_term( $data['category'], $data['taxonomy'], $product_id ) || get_woocommerce_currency() != $data['currency'] ) {
return $product_price_html; // Exit
}
if ( WC()->cart->display_prices_including_tax() ) {
$price = wc_get_price_including_tax( $product );
} else {
$price = wc_get_price_excluding_tax( $product );
}
return wc_price_custom( $price, $data['curr_symbol'] );
}
// On cart item line subtotal (Cart and Checkout pages) - Custom currency symbol
add_filter( 'woocommerce_cart_product_subtotal', 'change_cart_item_subtotal_currency_symbol', 10, 8 );
function change_cart_item_subtotal_currency_symbol( $product_subtotal, $product, $quantity, $cart ) {
// Loading your settings
$data = custom_currency_symbol_settings();
// Get the correct product ID
$product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
// Only for the defined product category and the defined currency
if ( ! has_term( $data['category'], $data['taxonomy'], $product_id ) || get_woocommerce_currency() != $data['currency'] ) {
return $product_price_html; // Exit
}
if ( $product->is_taxable() ) {
if ( $cart->display_prices_including_tax() ) {
$row_price = wc_get_price_including_tax( $product, array( 'qty' => $quantity ) );
$product_subtotal = wc_price_custom( $row_price, $data['curr_symbol'] );
if ( ! wc_prices_include_tax() && $cart->get_subtotal_tax() > 0 ) {
$product_subtotal .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>';
}
} else {
$row_price = wc_get_price_excluding_tax( $product, array( 'qty' => $quantity ) );
$product_subtotal = wc_price_custom( $row_price, $data['curr_symbol'] );
if ( wc_prices_include_tax() && $cart->get_subtotal_tax() > 0 ) {
$product_subtotal .= ' <small class="tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
}
}
} else {
$row_price = $product->get_price() * $quantity;
$product_subtotal = wc_price_custom( $row_price, $data['curr_symbol'] );
}
return $product_subtotal;
}
// Custom formatting price function replacement
function wc_price_custom( $price, $curr_symbol, $args = array() ){
extract( apply_filters( 'wc_price_args', wp_parse_args( $args, array(
'ex_tax_label' => false,
'currency' => '',
'decimal_separator' => wc_get_price_decimal_separator(),
'thousand_separator' => wc_get_price_thousand_separator(),
'decimals' => wc_get_price_decimals(),
'price_format' => get_woocommerce_price_format(),
) ) ) );
$unformatted_price = $price;
$negative = $price < 0;
$price = apply_filters( 'raw_woocommerce_price', floatval( $negative ? $price * -1 : $price ) );
$price = apply_filters( 'formatted_woocommerce_price', number_format( $price, $decimals, $decimal_separator, $thousand_separator ), $price, $decimals, $decimal_separator, $thousand_separator );
if ( apply_filters( 'woocommerce_price_trim_zeros', false ) && $decimals > 0 ) {
$price = wc_trim_zeros( $price );
}
$formatted_price = ( $negative ? '-' : '' ) .
sprintf( $price_format, '<span class="woocommerce-Price-currencySymbol">' . $curr_symbol . '</span>', $price );
$return = '<span class="woocommerce-Price-amount amount">' . $formatted_price . '</span>';
if ( $ex_tax_label && wc_tax_enabled() ) {
$return .= ' <small class="woocommerce-Price-taxLabel tax_label">' . WC()->countries->ex_tax_or_vat() . '</small>';
}
return apply_filters( 'wc_price', $return, $price, $args, $unformatted_price );
}
2) GLOBALLY (Much more easier):
The following code based on your code settings will change the currency symbol globally on cart and on checkout pages too, When 'cupones' product category is found in any cart item:
add_filter( 'woocommerce_currency_symbol', 'change_existing_currency_symbol', 10, 2 );
function change_existing_currency_symbol( $currency_symbol, $currency ) {
global $post, $product;
$custom_sym = 'ptos'; // <=== HERE define your currency symbol replacement
$custom_cur = 'EUR'; // <=== HERE define the targeted currency code
$category = array('cupones'); // <=== HERE define your product category(ies)
$taxonomy = 'product_cat';
// Cart and checkout
if( ( is_cart() || is_checkout() ) && $currency == $custom_cur ){
foreach( WC()->cart->get_cart() as $cart_item ){
if ( has_term( $category, $taxonomy, $cart_item['product_id'] ) ){
return $custom_sym; // Found! ==> we return the custom currency symbol
}
}
}
// Others Woocommerce product pages
if ( has_term( $category, $taxonomy ) && $currency == $custom_cur ) {
return $custom_sym;
}
return $currency_symbol;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
In Woocommerce I have a variable products with many variations and every variation has its own REGULAR price and SALE price.
I would like when user:
is logged in, the sale price will be the active price
is not logged in, the regular price will be the active price.
I have added this hooked function in my child theme function.php file:
add_filter( 'woocommerce_available_variation', 'my_variation', 10, 3);
function my_variation( $data, $product, $variation ) {
wc_delete_product_transients($variation->get_id());
$variation_id = $variation->get_id();
$variable_product1= new WC_Product_Variation($variation_id);
if(is_user_logged_in()){
$regular_price = $variable_product1 ->regular_price;
$data['price_html'] = woocommerce_price($regular_price);
return $data;
} else {
$sale_price = $variable_product1 ->sale_price;
$data['price_html'] = woocommerce_price($sale_price);
return $data;
}
}
The displayed price works… But when I add to cart any product it remains only with the sale price in in cart…
The code below will:
enable regular price for non logged users only everywhere
enable sale price for logged users only everywhere
hide the sale flash badge
remove the sale price range
The code:
// Variable and simple product displayed prices (removing sale price range)
add_filter( 'woocommerce_get_price_html', 'custom_get_price_html', 20, 2 );
function custom_get_price_html( $price, $product ) {
if( $product->is_type('variable') )
{
if( is_user_logged_in() ){
$price_min = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_sale_price('min') ) );
$price_max = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_sale_price('max') ) );
} else {
$price_min = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_regular_price('min') ) );
$price_max = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_regular_price('max') ) );
}
if( $price_min != $price_max ){
if( $price_min == 0 && $price_max > 0 )
$price = wc_price( $price_max );
elseif( $price_min > 0 && $price_max == 0 )
$price = wc_price( $price_min );
else
$price = wc_format_price_range( $price_min, $price_max );
} else {
if( $price_min > 0 )
$price = wc_price( $price_min);
}
}
elseif( $product->is_type('simple') )
{
if( is_user_logged_in() )
$active_price = wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) );
else
$active_price = wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) );
if( $active_price > 0 )
$price = wc_price($active_price);
}
return $price;
}
// Product Variation displayed prices
add_filter( 'woocommerce_available_variation', 'custom_variation_price', 10, 3);
function custom_variation_price( $data, $product, $variation ) {
$reg_price = wc_get_price_to_display( $variation, array( 'price' => $variation->get_regular_price() ) );
$sale_price = wc_get_price_to_display( $variation, array( 'price' => $variation->get_sale_price() ) );
if( is_user_logged_in() )
$data['price_html'] = wc_price( $sale_price );
else
$data['price_html'] = wc_price( $reg_price );
return $data;
}
// Set the correct prices in cart
add_action( 'woocommerce_before_calculate_totals', 'set_item_cart_prices', 20, 1 );
function set_item_cart_prices( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ){
if( ! is_user_logged_in() ){
$cart_item['data']->set_price( $cart_item['data']->get_regular_price() );
}
}
}
// Remove sale badge
remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_show_product_loop_sale_flash', 10 );
remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_sale_flash', 10 );
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Update: Enable back price suffix to a function that display customized product prices in WooCommerce
It worked for me! Thanks a lot for the code!
This code helps my customer to add prices for their "members" very easily.
They just complete regular and sale price.
Wholesale plugins are much more complex and are not needed in this case.
*I mean in the case that only logged in users should see the "sale price".
i have to arrange product price based on category . So every product in category A have price 5 ,
and in category B product price is 10 and in category c product price is 15 .
After this arrangement , when product is adding to cart , then i have to multiply product price by our margin . Currently our margin is 2.5.
So we write following codes in fucntions.php
add_filter('woocommerce_product_get_price', 'product_price_new', 10, 2);
function product_price_new($price, $product) {
if(!is_cart()){
if(has_term( 'accessories', 'product_cat' ,$product->id)){ $price=5; }
if(has_term( 'hoodies', 'product_cat' ,$product->id)){ $price=10; }
if(has_term( 'tshirts', 'product_cat' ,$product->id)){ $price=15;}
}
return $price;
}
add_filter( 'woocommerce_add_cart_item_data', 'margin_price', 30, 3 );
function margin_price( $cart_item_data, $product_id, $variation_id ) {
$the_id = $variation_id > 0 ? $variation_id : $product_id;
$product = wc_get_product( $the_id );
$product_price = (float) $product->get_price();
$cart_item_data['calculated-price'] = $product_price*2.5;
return $cart_item_data;
}
add_action( 'woocommerce_before_calculate_totals', 'add_caculted', 20, 1 );
function add_caculted( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ){
if( ! empty( $cart_item['calculated-price'] ) ){
// Set the calculated item price (if there is one)
$cart_item['data']->set_price( $cart_item['calculated-price'] );
}
}
}
Please see what happen .
For example if we are trying to add product in category hoodies , so price will be , 10 *2.5=25
(1) in cart page product pric is showing 25 , and this is correct .
[mywebsite.com/cart]
(2) In checkout page product price is showing 10, so the total is
coming as 10 . This is wrong it should be 25 .
(3) In the minicart that showing near the menu , it showing 1*10 and subtotal is 10 , but it NEED to show 1 *25 and subtotal = 25
Please help to solve this issue . What i missed ?
i tried all this code in default woocommerce storfront theme . https://woocommerce.com/storefront/
Only for simple products, you can try the following instead:
// Utility function
function get_special_product_category_prices( $price, $product_id ) {
// HERE your prices by product category
$prices_by_cat = array( 5 => 'accessories', 10 => 'hoodies', 15 => 't-shirts' );
foreach( $prices_by_cat as $key_price => $term ){
if( has_term( $term, 'product_cat', $product_id ) )
return $key_price;
}
return $price;
}
// Alter product displayed prices (for simple products only)
add_filter( 'woocommerce_get_price_html', 'alter_displayed_price_html', 20, 2 );
function alter_displayed_price_html( $price, $product ) {
if( $product->is_type('simple') ){
$raw_price = get_special_product_category_prices( $product->get_price(), $product->get_id() );
if( $raw_price > 0 )
$price = wc_price( wc_get_price_to_display( $product, array( 'price' => $raw_price ) ) );
}
return $price;
}
add_filter( 'woocommerce_add_cart_item_data', 'add_calculated_margin_price', 30, 3 );
function add_calculated_margin_price( $cart_item_data, $product_id, $variation_id ) {
$the_id = $variation_id > 0 ? $variation_id : $product_id;
$product = wc_get_product( $the_id );
$product_price = (float) get_special_product_category_prices( $product->get_price(), $product_id );
$cart_item_data['calculated-price'] = $product_price * 2.5;
return $cart_item_data;
}
add_action( 'woocommerce_before_calculate_totals', 'set_caculated_price', 20, 1 );
function set_caculated_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ){
if( ! empty( $cart_item['calculated-price'] ) ){
// Set the calculated item price (if there is one)
$cart_item['data']->set_price( $cart_item['calculated-price'] );
}
}
}
Code goes in function.php file of your active child theme (or theme). It should work.
I am looking for a way to replace €0,00 price for a WooCommerce (version 3.3.x) product with text, like 'Based on contract'. Preferably visible in the webshop and emails. Because of recent changes in WooCommerce the existing snippets aren't working anymore, like:
add_filter('woocommerce_get_price_html', 'changeFreePriceNotice', 10, 2);
function changeFreePriceNotice($price, $product) {
if ( $price == wc_price( 0.00 ) )
return 'FREE';
else
return $price;
}
Or
<?php
// Do not copy the opening <?php tag above
// Customize the Free! price output
add_filter( 'woocommerce_variable_free_price_html','wsm_custom_free_price' );
add_filter( 'woocommerce_free_price_html', 'wsm_custom_free_price' );
add_filter( 'woocommerce_variation_free_price_html', 'wsm_custom_free_price' );
function wsm_custom_free_price( $price ) {
// Edit content between single quotes below to desired output
return 'Prepaid Inventory';
}
Or
function my_wc_custom_get_price_html( $price, $product ) {
if ( $product->get_price() == 0 ) {
if ( $product->is_on_sale() && $product->get_regular_price() ) {
$regular_price = wc_get_price_to_display( $product, array( 'qty' => 1, 'price' => $product->get_regular_price() ) );
$price = wc_format_price_range( $regular_price, __( 'Free!', 'woocommerce' ) );
} else {
$price = '<span class="amount">' . __( 'Free!', 'woocommerce' ) . '</span>';
}
}
return $price;
}
add_filter( 'woocommerce_get_price_html', 'my_wc_custom_get_price_html', 10, 2 );
Here is the correct way to do it on Woocommerce 3+ (tested on WooCommerce 3.3.x and 3.5+ too):
// Product displayed prices
add_filter( 'woocommerce_get_price_html', 'free_price_custom_label', 20, 2 );
function free_price_custom_label( $price, $product ) {
if ( is_shop() || is_product_category() || is_product_tag() || is_product() ) {
// HERE your custom free price label
$free_label = '<span class="amount">' . __('Based on contract') . '</span>';
if( $product->is_type('variable') )
{
$price_min = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_price('min') ) );
$price_max = wc_get_price_to_display( $product, array( 'price' => $product->get_variation_price('max') ) );
if( $price_min != $price_max ){
if( $price_min == 0 && $price_max > 0 )
$price = wc_price( $price_max );
elseif( $price_min > 0 && $price_max == 0 )
$price = wc_price( $price_min );
else
$price = wc_format_price_range( $price_min, $price_max );
} else {
if( $price_min > 0 )
$price = wc_price( $price_min);
else
$price = $free_label;
}
}
elseif( $product->is_on_sale() )
{
$regular_price = wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) );
$sale_price = wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) );
if( $sale_price > 0 )
$price = wc_format_sale_price( $regular_price, $sale_price );
else
$price = $free_label;
}
else
{
$active_price = wc_get_price_to_display( $product, array( 'price' => $product->get_price() ) );
if( $active_price > 0 )
$price = wc_price($active_price);
else
$price = $free_label;
}
}
return $price;
}
// Product variation displayed prices
add_filter( 'woocommerce_variable_price_html', 'free_variation_price_custom_label', 20, 2 );
function free_variation_price_custom_label( $price, $product ) {
// HERE your custom free price label
$free_label = '<span class="amount">' . __('Based on contract') . '</span>';
if( $product->is_on_sale() )
{
$regular_price = wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) );
$sale_price = wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) );
if( $sale_price > 0 )
$price = wc_format_sale_price( $regular_price, $sale_price );
else
$price = $free_label;
}
else
{
$active_price = wc_get_price_to_display( $product, array( 'price' => $product->get_price() ) );
if( $active_price > 0 )
$price = wc_price($active_price);
else
$price = $free_label;
}
return $price;
}
// Cart items displayed prices and line item subtotal
add_filter( 'woocommerce_cart_item_subtotal', 'free_cart_item_price_custom_label', 20, 3 );
add_filter( 'woocommerce_cart_item_price', 'free_cart_item_price_custom_label', 20, 3 );
function free_cart_item_price_custom_label( $price, $cart_item, $cart_item_key ) {
// HERE your custom free price label
$free_label = '<span class="amount">' . __('Based on contract') . '</span>';
if( $cart_item['data']->get_price() > 0 )
return $price;
else
return $free_label;
}
// Order items displayed prices (and also email notifications)
add_filter( 'woocommerce_order_formatted_line_subtotal', 'free_order_item_price_custom_label', 20, 3 );
function free_order_item_price_custom_label( $subtotal, $item, $order ) {
// HERE your custom free price label
$free_label = '<span class="amount">' . __('Based on contract') . '</span>';
if( $order->get_line_subtotal( $item ) > 0 )
return $subtotal;
else
return $free_label;
}
This code goes on function.php file of your active child theme (or theme). Tested and works.