skip to Main Content

My question is based on code provided in answer (by LoicTheAztec and Xandl) to another question ‘Set Product sale price conditionally based on custom fields in Woocommerce‘. Whilst the foundation code is based on answers to that question, I have developed it a little further to meet a slightly more complex requirement.

The question: How do I automate regular price changes based on a static date within a custom field for both simple and variable products?

To give a bit more of an explanation; I am trying to create automated price drops to the regular price of a WooCommerce product based on a static date entered into a custom field ‘wooct_time_start’.

The code snippet below works fine for simple products and is currently set to change the price to the number of ‘$remaining_days’ before the ‘wooct_time_start’ date/time, but I cannot seem to get the second half of code to work with variable products and this is where I need some help?

add_filter('woocommerce_product_get_price', 'conditional_product_sale_price', 20, 6);
add_filter('woocommerce_product_get_sale_price', 'conditional_product_sale_price', 20, 6);
add_filter('woocommerce_product_variation_get_price', 'conditional_product_sale_price', 20, 6);
add_filter('woocommerce_product_variation_get_sale_price', 'conditional_product_sale_price', 20, 6);
add_filter('woocommerce_variation_prices_price', 'conditional_product_sale_price', 20, 6);
add_filter('woocommerce_variation_prices_sale_price', 'conditional_product_sale_price', 20, 6);

function conditional_product_sale_price($price, $product){
    
    if($product->is_type('simple')){

        $date = get_post_meta($product->get_id(), 'wooct_time_start', true);

        if(!empty($date)){
            $date_time = (int) strtotime($date);
            $now_time = (int) strtotime("now");
            $remaining_days = floor(($date_time - $now_time) / 86400);
    
            if($remaining_days <= 30){
                $price = $remaining_days;
            }elseif($remaining_days >= 31 && $remaining_days <= 60){
                $price = $remaining_days;
            }elseif($remaining_days >= 61 && $remaining_days <= 90){
                $price = $remaining_days;
            }elseif($remaining_days >= 91 && $remaining_days <= 120){
                $price = $remaining_days;
            }elseif($remaining_days >= 121 && $remaining_days <= 150){
                $price = $remaining_days;
            }elseif($remaining_days > 150){
                $price = $remaining_days;
            }
        }
        
        return $price;
            
    }if($product->is_type('variable')){

            $children_ids = $product->get_children();
            $date = get_post_meta($product->get_id(), 'wooct_time_start', true);
            
            foreach( $children_ids as $child_id ){

                $variation = wc_get_product($child_id);
                $var_price = $variation->get_price();
                
                if(!empty($date)){
                    $date_time = (int) strtotime($date);
                    $now_time = (int) strtotime("now");
                    $remaining_days = floor(($date_time - $now_time) / 86400);
                    
                    if($remaining_days <= 30){
                        $var_price = $remaining_days;
                    }elseif($remaining_days >= 31 && $remaining_days <= 60){
                        $var_price = $remaining_days;
                    }elseif($remaining_days >= 61 && $remaining_days <= 90){
                        $var_price = $remaining_days;
                    }elseif($remaining_days >= 91 && $remaining_days <= 120){
                        $var_price = $remaining_days;
                    }elseif($remaining_days >= 121 && $remaining_days <= 150){
                        $var_price = $remaining_days;
                    }elseif($remaining_days > 150){
                        $var_price = $remaining_days;
                    }
                }
                
                return $price;
                
            }
    }   
}

I have attempted various iterations to the code, but without success:

  • Changing the position of the line $date = get_post_meta($product->get_id(), 'wooct_time_start', true);
  • Changing the line $var_price = $variation->get_price(); to $var_price = $product->get_price();
  • I have played with the code relating to woocommerce_get_variation_prices_hash becasue of the stored transients, but I still do not know how it directly relates to my code despite several hours of research online.

UPDATE:

I have been able to create the following updated code using the answers provided in the article ‘Change product prices via a hook in WooCommerce 3+‘.

This new code has one remaining issue – It doesn’t seem to successfully be updating the prices for any of the ‘variations’. It is working for ‘Simple’ and ‘Variable’ products however!

If anyone is able to get this new code working with ‘variations’ too, then this would answer the question.

function product_life_cycle_main_function($price, $product){

        $date = get_post_meta($product->get_id(), 'wooct_time_start', true);

        if(!empty($date)){
            $date_time = (int) strtotime($date);
            $now_time = (int) strtotime("now");
            $remaining_days = floor(($date_time - $now_time) / 86400);
    
            if($remaining_days <= 30){
                $price = $remaining_days;
            }elseif($remaining_days >= 31 && $remaining_days <= 60){
                $price = $remaining_days;
            }elseif($remaining_days >= 61 && $remaining_days <= 90){
                $price = $remaining_days;
            }elseif($remaining_days >= 91 && $remaining_days <= 120){
                $price = $remaining_days;
            }elseif($remaining_days >= 121 && $remaining_days <= 150){
                $price = $remaining_days;
            }elseif($remaining_days > 150){
                $price = $remaining_days;
            }
        }
        return $price;
}

add_filter('woocommerce_product_get_price', 'product_life_cycle_custom_price', 99, 2);
add_filter('woocommerce_product_get_regular_price', 'product_life_cycle_custom_price', 99, 2);
add_filter('woocommerce_product_variation_get_regular_price', 'product_life_cycle_custom_price', 99, 2);
add_filter('woocommerce_product_variation_get_price', 'product_life_cycle_custom_price', 99, 2);
    function product_life_cycle_custom_price($price, $product) {
        return product_life_cycle_main_function($price, $product);
    }

add_filter('woocommerce_variation_prices_price', 'product_life_cycle_custom_variable_price', 99, 3);
add_filter('woocommerce_variation_prices_regular_price', 'product_life_cycle_custom_variable_price', 99, 3);
    function product_life_cycle_custom_variable_price($price, $variation, $product) {
        wc_delete_product_transients($variation->get_id());
        return product_life_cycle_main_function($price, $product);
    }

add_filter('woocommerce_get_variation_prices_hash', 'product_life_cycle_variation_prices_hash', 99, 3);
    function product_life_cycle_variation_prices_hash($price_hash, $product, $for_display) {
        $price_hash[] = product_life_cycle_main_function($price, $product);
        return $price_hash;
    }

2

Answers


  1. Chosen as BEST ANSWER

    Using the advice given by Diego, I was able to add the following to make the code work correctly:

    function product_life_cycle_main_function($price, $product){
        
        $product_id = ($product->get_parent_id() > 0) ? $product->get_parent_id() : $product->get_id();
        
        $date = get_post_meta($product_id, 'wooct_time_start', true);
    
            if(!empty($date)){
                $date_time = (int) strtotime($date);
                $now_time = (int) strtotime("now");
                $remaining_days = floor(($date_time - $now_time) / 86400);
        
                if($remaining_days <= 30){
                    $price = $remaining_days;
                }elseif($remaining_days >= 31 && $remaining_days <= 60){
                    $price = $remaining_days;
                }elseif($remaining_days >= 61 && $remaining_days <= 90){
                    $price = $remaining_days;
                }elseif($remaining_days >= 91 && $remaining_days <= 120){
                    $price = $remaining_days;
                }elseif($remaining_days >= 121 && $remaining_days <= 150){
                    $price = $remaining_days;
                }elseif($remaining_days > 150){
                    $price = $remaining_days;
                }
            }
            
            return $price;
            
    }
    
    add_filter('woocommerce_product_get_price', 'product_life_cycle_custom_price', 99, 2);
    add_filter('woocommerce_product_get_regular_price', 'product_life_cycle_custom_price', 99, 2);
    add_filter('woocommerce_product_variation_get_regular_price', 'product_life_cycle_custom_price', 99, 2);
    add_filter('woocommerce_product_variation_get_price', 'product_life_cycle_custom_price', 99, 2);
        function product_life_cycle_custom_price($price, $product) {
            return product_life_cycle_main_function($price, $product);
        }
    
    add_filter('woocommerce_variation_prices_price', 'product_life_cycle_custom_variable_price', 99, 3);
    add_filter('woocommerce_variation_prices_regular_price', 'product_life_cycle_custom_variable_price', 99, 3);
        function product_life_cycle_custom_variable_price($price, $variation, $product) {
            wc_delete_product_transients($variation->get_id());
            return product_life_cycle_main_function($price, $product);
        }
    
    add_filter('woocommerce_get_variation_prices_hash', 'product_life_cycle_variation_prices_hash', 99, 3);
        function product_life_cycle_variation_prices_hash($price_hash, $product, $for_display) {
            global $price;
            $price_hash[] = product_life_cycle_main_function($price, $product);
            return $price_hash;
        }
    

  2. I would suggest to rewrite the logic that fetches the data to make it more robust. The checks described in the accepted answer fails if the product is not simple, variable or variation, but it can be made more generic. Here’s an example of how to do that:

    function product_life_cycle_main_function($price, $product){
        // Determine the product ID to use
        // - Parent product ID for variations
        // - Product ID for all other products
        $meta_product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
    
        // The above can also be simplified as follows:
        // - If the product has a parent, take the meta from the parent
        // - If the product doesn't have a parent, take the meta from the product
        //
        // This check would also work with other product types, such as bundled products, subscriptions, etc
        //$meta_product_id = ($product->get_parent_id() > 0) ? $product->get_parent_id() : $product->get_id();
    
        $date = get_post_meta($meta_product_id, 'wooct_time_start', true);
    
        // Rest of the code...
    
        return $price;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search