Search code examples
phpwordpresswoocommerceproductorders

Replace product zero displayed price with a custom text in Woocommerce 3


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 );

Solution

  • 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.