Search code examples
phpwordpresswoocommerceproduct

Add a "Sale" badge if the sale price is filled for variations in WooCommerce


In WooCommerce, for a simple product I can add a "Sale!" badge this way:

add_action( 'woocommerce_before_shop_loop_item_title', function() {
    global $product; 
    $akc = get_post_meta(get_the_ID(), '_sale_price', true);
    if ( $akc > 0 ) {
        echo '<span class="onsale soldout">Sale!</span>';
    }
});

For variable products, it doesn't work…
How to get the value of all variation fields with the 'sale_price'?
So how to make it work for variable products?

Turned out only for everyone variable products by this code:

add_action( 'woocommerce_before_shop_loop_item_title', function($price, $_this) {
    global $product; 

    if($product->product_type == 'variable') {

        $variation_rrp_price = get_sale_price( $variation_price, $product_id );

        $t = get_post_meta(get_the_ID(), $prices_array['_sale_price'], $variation_price); var_dump($t);
        if ( !empty ($t)  ) {
            echo '<span class="onsale soldout">Sale!</span>';
        }
    }
});

UPDATE

So I get custom price by this code:

function get_rrp_price( $price, $product_id ) {
    $rooms2 = get_post_meta( $product_id, 'rooms2', true );
    if ( '' === $rooms2) {
        $rooms2 = 1; 
    }

    $kurs = 1;
    $kurs2 = 10;
    $kurs3 = 100;

    switch ( $rooms2 ) {
        case 1:
            $rrp_price = $price * $kurs2;
            break;
        case 2:
            $rrp_price = $price * $kurs3;
            break;
        default:
            $rrp_price = $price * $kurs;
            break;
    }

    return $rrp_price;
}

function filter_woocommerce_get_price( $price, $_this ) {
    $product_id = $_this->id;
    $rrp_price = get_rrp_price( $price, $product_id );
    update_post_meta( $product_id, 'rrp_price', $rrp_price );

    return $rrp_price;
}

function filter_736700_woocommerce_product_variation_get_price( $price, $_this) {
    if ( 'product_variation' === $_this->post_type ) {
        $data            = (object) $_this->get_data();
        $variation_price = $data->price;
        $product_id       = $data->parent_id;
        $variation_rrp_price = get_rrp_price( $variation_price, $product_id );
        $price = $variation_rrp_price;
    }

    return $price;
}

add_filter( 'woocommerce_product_variation_get_price', 'filter_736700_woocommerce_product_variation_get_price', 10, 2);

function filter_736700_woocommerce_variation_prices( $prices_array, $product, $include_taxes ) {


    $product_id = $product->id;

    foreach ( $prices_array['price'] as $key => $price ) {
        $prices_array['price'][ $key ] = get_rrp_price( $price, $product_id );
    }

    foreach ( $prices_array['regular_price'] as $key => $price ) {
        $prices_array['price'][ $key ] = get_rrp_price( $price, $product_id );
    }

    foreach ( $prices_array['sale_price'] as $key => $price ) {
        $prices_array['price'][ $key ] = get_rrp_price( $price, $product_id );
    }

    return $prices_array;
}

add_filter( 'woocommerce_variation_prices', 'filter_736700_woocommerce_variation_prices', 10, 3 );


function filter_738363_woocommerce_product_variation_get_regular_price( $price, $_this ) {
    if ( 'product_variation' === $_this->post_type ) {
        $data            = (object) $_this->get_data();
        $variation_price = $data->regular_price;
        $product_id       = $data->parent_id;
        $variation_rrp_price = get_rrp_price( $variation_price, $product_id );
        update_post_meta( $product_id, $data->name . ' - regular' , $variation_rrp_price );
        $price = $variation_rrp_price;
    }

    return $price;
}

add_filter( 'woocommerce_product_variation_get_regular_price', 'filter_738363_woocommerce_product_variation_get_regular_price', 10, 2);

But after this "Sale!" not assigned anymore (only for variable products)


Solution

  • To make your code work for all products types, you should use WC_Product is_on_sale() method. This way you will only have one function for all product types this way:

    add_action( 'woocommerce_before_shop_loop_item_title', 'custom_shop_loop_on_sale_badge' );
    function custom_shop_loop_on_sale_badge(){
        global $product;
    
        if($product->is_on_sale())
            echo '<span class="onsale soldout">Sale!</span>';
    }
    

    Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

    Tested and works.


    Update (related to the update in your question).

    To get something functional with the your sale calculated price, try this instead:

    // Prices calculation common function
    function get_rrp_price( $price, $product_id ) {
        $rooms2 = get_post_meta( $product_id, 'rooms2', true );
        if ( '' === $rooms2 )
            $rooms2 = 1;
    
        if ( $rooms2 == 1 )
            $price *= 10;
        elseif ( $rooms2 == 2 )
            $price *= 100;
    
        return $price;
    }
    
    // Simple products prices
    add_filter( 'woocommerce_product_get_price', 'custom_simple_product_price', 20, 2 );
    add_filter( 'woocommerce_product_get_regular_price', 'custom_simple_product_price', 20, 2 );
    function custom_simple_product_price( $price, $product ) {
        $price = get_rrp_price( $price, $product->get_id() );
        update_post_meta( $product->get_id(), 'rrp_price', $price );
    
        return $price;
    }
    
    // Variable products: Selected variation prices
    add_filter( 'woocommerce_variation_prices_price', 'custom_variations_prices', 10, 3 );
    add_filter( 'woocommerce_variation_prices_regular_price', 'custom_variations_prices', 10, 3 );
    add_filter( 'woocommerce_variation_prices_sale_price', 'custom_variations_prices', 10, 3 );
    function custom_variations_prices( $price, $variation, $product ) {
        if (  $variation->is_type('variation') ) {
            $product_id = $product->get_id();
    
            $price = get_rrp_price( $price, $product_id );
        }
        return $price;
    }
    
    // Variable products: Min/Max variations prices
    add_filter( 'woocommerce_product_variation_get_regular_price', 'custom_variations_get_prices' , 10, 2 );
    add_filter( 'woocommerce_product_variation_get_sale_price', 'custom_variations_get_prices' , 10, 2 );
    add_filter( 'woocommerce_product_variation_get_price', 'custom_variations_get_prices', 10, 2 );
    function custom_variations_get_prices( $price, $variation ) {
    
        if (  $variation->is_type('variation') ) {
            $parent_product_id = $variation->get_parent_id();
            $rrp_price = get_rrp_price( $price, $product_id );
    
            // Adding/Updating "rrp regular price" custom field
            $regular_price = $variation->get_regular_price();
            if( $regular_price == $price )
                update_post_meta( $product_id, $variation->get_name() . ' - regular' , $rrp_price );
    
            $price = $rrp_price;
        }
        return $price;
    }
    

    Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

    Tested and works.