Reputation: 276
I have to mention what I have been doing in order to achieve that, and give a little background on the functionality.
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.
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.
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.
Upvotes: 1
Views: 1336
Reputation: 276
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.
Upvotes: 0