1
votes

Scenario

  • WP Ajax is not used at the Add to cart event, so, the single product page reloads completely once the user adds something to the cart, it is not my installation so I cannot change freely that WooCommerce setting.
  • There is a certain message that is displayed once the user add to cart an item, as a WooCommerce notice at the single product layout.
  • This message must not change if the product allows backorders, it must change if it is "In Stock", a single string must be added.
  • The store have simple and variable products so the feature must work properly on any case.

I have to mention what I have been doing in order to achieve that, and give a little background on the functionality.

First Approach

A custom message was added directly through 'wc_add_to_cart_message_html'. This was implemented due to a previous request to customize the aforementioned message without further requirements.


Second Approach (current, because it is still on development)

The previously mentioned message changes if it is found that the product doesn't allows backorders, the change is made through jQuery at 'woocommerce_single_product_summary'.

A product object is created and it is asked if the product allows backorders through the following method:

    $product->backorders_allowed()

That would do just fine if it wasn't that there are variable products too.

What I mean is that despite a variable product can be configured to allow backorders, I mean, the parent product of all the possible variations, the inventory management relies right now on the variations, every variation have its own "In Stock" stock status setting, and, one among many could have "On backorder" stock status setting.


Third approach (hypothetical)

In order to get the current variation ID I can get it here on the DOM:

    $('input.variation_id').val();

Why?, because I want to use that value to call the WooCommerce product variation constructor and check yet again but now at a variation level if the product is able to be ordered on backorder, like this:

    $p_variation = new WC_Product_Variation( $var_id );
    $p_variation->backorders_allowed()

But I have a problem, I don't know how to get this DOM value (the current variation that was just added to the cart) and send it to the function that would contain the latest mentioned constructor and method.

In other cases I have been able to send DOM data to the server (to be processed by PHP) by invoking a defined function as an action through WP Ajax, alongside with data and instructions to take into account if the action was successfully executed, on the change event of the variation select html object on the DOM, but with the reload of the whole page I find myself lost.

Because is quite different to invoke something through a select changing than on a submit of the add to cart form.

I don't know if it is possible to call the backorders_allowed method at all, I assume that a product variation have the same properties that a parent product.

I lack of ideas right now and I would appreciate if someone could help me a little bit with this.

1
Just to confirm: if I have a variable product called tshirt, and I add tshirt - red to my cart, a string needs to be added to the "Added to cart" string that shows up in the woocommerce message area at the top only if the red tshirt variations allows backorders?Frits
On the contrary, a message needs to be added only if the red tshirt is "In Stock". If the red tshirt allows backorders it shouldn't add anything to the WooCommerce Notices area once the item is added to cart.Luis

1 Answers

0
votes

Solution

Add the following to the functions.php of the child theme, theme or custom plugin that you are using in order to achieve this functionality.

First Function

<?php
/* Server side function that is invoked via ajax */
function get_variation_id_added_to_cart(){
   $variation_id = $_POST['id']; 
   /* When the server receives the post data it should receive this value in order to work. */
   $stockstatus = get_post_meta( $variation_id, '_stock_status', true );
   /* Retrieving stock status per ID, if the id belongs to a product
      it will show a product stock status, if the id belongs to a variation
      it will show a variation stock status. */
   if ($stockstatus != 'instock') {
      $aditional_copy = ''; // If the item is not in stock the custom message would be blank.
   }else{
      /* On the contrary, if the item is in stock it will show the following custom message */
      $aditional_copy = ' <strong>Add another item and receive it in 3 working days.</strong>' ;
   }
   /* Now, let's create a response array */
   $response= array(
      'message'   => $aditional_copy,
   );
   /* Is like a sort of return but as a JSON encoded content */
   wp_send_json_success($response);
}
/* Code that allows to invoke the server side function. */
add_action( 'wp_ajax_variation_id_added_to_cart', 'get_variation_id_added_to_cart');
/* Code that allows to invoke the server side function in a non private way. */
add_action( 'wp_ajax_nopriv_variation_id_added_to_cart', 'get_variation_id_added_to_cart');

Second Function


/* Attach the custom function that makes the js magic to the wp_footer function. */
add_action('wp_footer','after_add_to_cart');
/* The function that sends the variation id to the server side to make a process from it. */
function after_add_to_cart(){
    /* Assure that this will only work if a single product template is present */
    if ( is_product() ){
        /* Create a product object, when you are at a single product if you don't tell anything else it takes as parameter the current product id */
        global $product;
        /* Now we know that this is the current product and will check if it is a variable one */
        if ($product->is_type('variable')) {
            /* If it is a variable product let's put a round zero on the var aux for the product id */
            $p_id = 0;
        }else{
            /* If it is not a variable product let's put the current product id in here */
            $p_id = $product->get_id();
        }
        /* Let's close the php tags and try a little js. */
        ?>
            <!-- The javascript that is responsible of sending
                 the variation id from the client side to the server side -->
            <script type="text/javascript">
                 /* I like to start with a semicolon my jQuery functions, it works
                    miracles when you have extremely complex environments with lots of
                    different js libraries, it cuts everything. */
                ;(function($){
                    /* Your document is ready so it begins */
                    $(document).ready(function() {
                        /* Let's equal the variation id on the client side
                           to zero */
                        var variation_id = 0;
                        /* Let's put a timeout, because client side WooCommerce
                           always has a bit of delay */
                        setTimeout(function() {
                            /* Now, let's get the current product variation id,
                               the real one */
                            var variation_id = $('input.variation_id').val();
                            /* Protect your WP Ajax URL at all costs,
                               the following will work but is not recommended.
                               Also this thing is the one that make it possible
                               to send and retrieve data from the server side */
                            var ajaxurl = "<?php echo admin_url('admin-ajax.php'); ?>";
                            /* Now the parameters, the name of the action that we
                               declared way back and the id that we are going to pass
                               but with a twist. Not always we are going to pass a
                               variation id, sometimes we are going to pass
                               a product id. */
                            var parameters = {
                                action: 'variation_id_added_to_cart',
                                <?php
                                if ($p_id > 0) {
                                /* if the product id aux is more than zero that means 
                                   that our product is a simple product (that has no
                                   variations). */
                                    ?>
                                    id: <?php echo $p_id; ?>
                                    <?php
                                }else{
                                /* if the product id aux is equal to zero that means 
                                   that our product is a variable product and we 
                                   should check the current variation id, to send it
                                   to the server side function. */
                                    ?>
                                    id: variation_id
                                    <?php
                                }
                                ?>
                            };
                            /* Now it begins, we determine the parameters that are 
                               going to be used in the execution, and what to do if 
                               the execution is successful */
                            $.ajax({
                                url: ajaxurl,
                                type: 'POST',
                                data: parameters,
                                success: function (data) { var initial_output = JSON.parse(data); var final_output = initial_output.data.message;  $('div.woocommerce-message').append(final_output); },
                                dataType: 'html'
                            });
                            /* A */
                            console.log('inside timeout: '+variation_id);
                        },1000);
                        /* B */
                        console.log('outside timeout: '+variation_id);
                    });
                })(jQuery);
            </script>
        <?php
    }
}
?>

You can check that in B the value is always zero, because that code runs immediately after the document is ready and in A (if it is a variable product) is always the product variation id, because that code runs with a delay of a second.