On cart items stock issue disable WooCommerce Place order checkout button - php

At the moment, if an item is out of stock a message appears in the checkout page:
Sorry, we do not have enough "xxx" in stock to fulfil your order (2 available). We apologise for any inconvenience caused.
Hence If that message appears, then I want to disable the "Proceed to checkout" button on the page by simply removing it.
If it that message doesn't appear, then display the "Proceed to checkout" button.
I'll obviously create an IF statement so that if it's true then display if not, don't display etc.
Here's my "Proceed to checkout" button code:
<input type="submit" name="cart_submit" class="checkout-button button alt wc-forward" style="text-transform: capitalize;" value="<?php esc_html_e( 'Proceed to checkout', 'woocommerce' ); ?>" />
So is there a method that I can call in Woocommerce to see if that error message has been called?
I tried scanning the entire webpage for that message and if true, execute xyz but that didn't work (could be sessions).
Any help would greatly be appreciated.

Based on WC_Cart check_cart_item_stock() method source code, that displays the error code of your question, The first function will check cart items stock as a conditional function returning true if everything is all right or false if an error has been displayed mentioning that there is a stock issue on cart items.
The second function will display a disabled greyed "Place Order" button if there is a stock issue on cart items.
function wc_check_cart_item_stock() {
$product_qty_in_cart = WC()->cart->get_cart_item_quantities();
$current_session_order_id = isset( WC()->session->order_awaiting_payment ) ? absint( WC()->session->order_awaiting_payment ) : 0;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$product = $values['data'];
// Check stock based on stock-status.
if ( ! $product->is_in_stock() ) {
return false;
}
// We only need to check products managing stock, with a limited stock qty.
if ( ! $product->managing_stock() || $product->backorders_allowed() ) {
continue;
}
// Check stock based on all items in the cart and consider any held stock within pending orders.
$held_stock = wc_get_held_stock_quantity( $product, $current_session_order_id );
$required_stock = $product_qty_in_cart[ $product->get_stock_managed_by_id() ];
if ( $product->get_stock_quantity() < ( $held_stock + $required_stock ) ) {
return false;
}
}
return true;
}
add_filter( 'woocommerce_order_button_html', 'disable_order_button_html' );
function disable_order_button_html( $button ) {
if( wc_check_cart_item_stock() ) {
return $button;
} else {
return '<a class="button alt disabled" style="cursor:not-allowed; text-align:center">' .__('Place order', 'woocommerce') . '</a>';
}
}
Disabled greyed "Place order" button on checkout page
Code goes in function.php file of your active child theme (or active theme). Tested and works.
If you want to remove the checkout "Place Order" button instead replace:
return '<a class="button alt disabled" style="cursor:not-allowed; text-align:center">' .__('Place order', 'woocommerce') . '</a>';
with:
return '';
Related: Customizing checkout "Place Order" button output html

Woocommerce has a special feature of having product value using global $product.
you can access your product stock quantity using the following code.
global $product;
$quantity = $product->get_stock_quantity();
if($quantity < 1){
//take decision.
}

Related

Avoid checkout for mixed backorder and normal items in Woocommerce

Is it possible to disable checkout if there is backorder item mixed with in stock items.
The code so far is displaying message if there is mixed items in the cart, but they still can checkout the order.
We are using Preorder plugin and on the settings, the preorder and onhand cant be mixed in cart. Below are settings of plugin.
Prevent mixing products If you enable this option, the cart cannot contain Pre-Order products and regular products at the same time.(enabled) But it only work if there is no items present in the cart.
Allow sales of out of stock products By enabling this option, Pre-Order products with no stock can be purchased. (enabled and allowed backorder) All items can be Preorder once stocks become zero.
Problem is if there is already items in cart they can checkout preorder and regular product. Please check example below
I put Product A(5 stocks) and B(10 stocks) in the cart but I dont want to checkout right away.
Then some one purchased the Product A and stocks become 0 (and Product A turn to preorder)
But if I proceed to checkout Product A(0 stocks and preorder) and B(10 stocks)so its already mixed in cart and I can proceed to checkout because backorder is allowed in settings.
Is it possible to automatically delete the Product A in cart or disable checkout?
add_action( 'woocommerce_review_order_before_payment', 'es_checkout_add_cart_notice' );
function es_checkout_add_cart_notice() {
$message = "You have a PREORDER item/s in your cart! Do not mix it if you're ordering on-hand item/s or IGNORE this message if you are ordering all pre-order item/s.";
if ( es_check_cart_has_backorder_product() )
wc_add_notice( $message, 'error' );
}
function es_check_cart_has_backorder_product() {
foreach( WC()->cart->get_cart() as $cart_item_key => $values ) {
$cart_product = wc_get_product( $values['data']->get_id() );
if( $cart_product->is_on_backorder() )
return true;
}
return false;
}
Try the following, that will really check for mixed items and will throw an error message avoiding:
"proceed to checkout" (in cart page)
placing order (checkout page)
The code:
// Display a custom notice when mixed items (backorder items and normal) avoiding checkout and "proceed to checkout" too
add_action( 'woocommerce_checkout_process', 'display_custom_error_notice' );
add_action( 'woocommerce_check_cart_items', 'display_custom_error_notice' );
function display_custom_error_notice() {
$message = __("You have a PREORDER item/s mixed with normal items. They can not be mixed.", "woocommerce");
if ( has_mixed_products() )
wc_add_notice( $message, 'error' );
}
// Utility function checking for mixed items (backorder items and normal)
function has_mixed_products() {
$on_backorder = $normal = false;
foreach( WC()->cart->get_cart() as $cart_item ) {
if( $cart_item['data']->is_on_backorder() )
$on_backorder = true;
else $normal = true;
}
return $on_backorder && $normal ? true : false;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
On cart page:
On checkout page:
Now is also possible to remove mixed items from cart throwing a notice…
With woocommerce mostly everything is possible, depending on your skills and on time to spend.
What about this?
...
if ( es_check_cart_has_backorder_product() ) {
add_filter('woocommerce_order_button_html', 'sg_remove_payment_button');
}
...
function sg_remove_payment_button ($button){
$output = '<div id="payments-disabled">';
$output .= 'Sorry, you cannot complete this order';
$output .= '</div>';
$output .= '<style>';
$output .= '.payment_methods, .wc-terms-and-conditions {display: none !important}';
$output .= '</style>';
return $output;
}

Change add to cart button color and disable it for out of stock products in Woocommerce

In woocommerce I have changed the add to cart button redirect to add to checkout page.
When some products are out of stock in categories or homepage the add to checkout button misses the content icon.
How Can I change the color of the button using php and disable it for button pressed event
Shall I use something like:
add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_stock', 10 );
function woocommerce_template_loop_stock() {
global $product;
if ( ! $product->managing_stock() && ! $product->is_in_stock() )
echo '<p class="stock out-of-stock">Out of Stock</p>';
}
But I am a bit confused
Try the following code:
// For Woocommerce version 3 and above only
add_filter( 'woocommerce_loop_add_to_cart_link', 'filter_loop_add_to_cart_link', 20, 3 );
function filter_loop_add_to_cart_link( $button, $product, $args = array() ) {
if( $product->is_in_stock() ) return $button;
// HERE set your button text (when product is not on stock)
$button_text = __('Not available', 'woocommerce');
// HERE set your button STYLING (when product is not on stock)
$color = "#777"; // Button text color
$background = "#aaa"; // Button background color
// Changing and disbling the button when products are not in stock
$style = 'color:'.$color.';background-color:'.$background.';cursor:not-allowed;';
return sprintf( '<a class="button disabled" style="%s">%s</a>', $style, $button_text );
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Replace ajax add to cart for specific products based on a custom field in Woocommerce

I've got AJAX add to cart enabled for my products which works great for 95% of them.
There are a few for which I need to disable the AJAX add to cart, so users are forced to go to the single product page and add to cart from there. I would be wanting to disable it based on the value of a custom meta key called "customizable_product" which is just a checkbox.
Is this achievable? I've searched around and haven't been able to find any information.
Updated: This can be done with the following hooked function, that will display a custom button linked to the single product page for a custom fields:
// Replacing the button add to cart by a link to the product in Shop and archives pages
add_filter( 'woocommerce_loop_add_to_cart_link', 'conditionally_replacing_ajax_add_to_cart_button', 10, 2 );
function conditionally_replacing_ajax_add_to_cart_button( $button, $product ) {
$custom_field = get_post_meta( $product->get_id(), 'customizable_product', true );
// When custom field exist
if( ! empty( $custom_field ) ){
$button_text = __("View product", "woocommerce");
$button = '<a class="button" href="' . $product->get_permalink() . '">' . $button_text . '</a>';
}
return $button;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

WooCommerce - Empty Cart on Page Reload

I have skipped the cart on my course membership site so 'Buy Now' brings you straight to checkout.
However, if you were logged in when you clicked 'Buy Now' then exit without buying, the item remains in the cart the next time you are logged in. If you go to purchase the same item during the next visit, it says "This item is already in your cart" but since I have the cart hidden from the front end, they can't access it.
Is it possible to empty the cart when page reloads with WooCommerce so it always goes straight to checkout when the user clicks 'Buy Now'?
Seems you're selling product individually. In this solution we're bypassing the filter hook woocommerce_add_to_cart_sold_individually_found_in_cart. When $found_in_cart is true users getting the message "This item is already in your cart". That's why we're resetting the quantity to 1. For more details please check https://docs.woocommerce.com/wc-apidocs/source-class-WC_Cart.html#1064
function op_bypass_add_to_cart_sold_individually_found_in_cart( $found_in_cart, $product_id ) {
if ( $found_in_cart ) {
$cart_contents = WC()->cart->get_cart_contents();
foreach ( $cart_contents as $key => $item ) {
if ( $product_id === $item['product_id'] ) {
WC()->cart->set_quantity( $key, 1 );
break;
}
}
return false;
}
return $found_in_cart;
}
add_filter( 'woocommerce_add_to_cart_sold_individually_found_in_cart', 'op_bypass_add_to_cart_sold_individually_found_in_cart', 10, 2 );
In my case " WC()->cart->set_quantity( $key, 1 );" from the answer #obiPlabon didn't worked proper, so I simplified function.
Since $found_in_cart is already fire only when amount of sold individually products in cart is more then one, I decided to simplify code and just make redirect to checkout page just it run.
if ( $found_in_cart ) {
global $woocommerce;
wp_redirect( wc_get_checkout_url() );
exit;
}

WooCommerce Variable Product notice Issue - please choose product options

I'm building an e-commerce site. I'm having some trouble with WooCommerce Variable Product.
The "Add to Cart" button works fine with simple products, but does not work with variable products. It gives a "Please choose product options…" notice.
I looked everywhere and tried several suggestions online, none of them work. So I looked into WooCommerce source file: class-wc-form-handler.php.
In the function add_to_cart_handler_variable:
function add_to_cart_handler_variable( $product_id ) {
$adding_to_cart = wc_get_product( $product_id );
$variation_id = empty( $_REQUEST['variation_id'] ) ? '' : absint( $_REQUEST['variation_id'] );
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
$missing_attributes = array();
$variations = array();
$attributes = $adding_to_cart->get_attributes();
$variation = wc_get_product( $variation_id );
...
if ( $missing_attributes ) {
wc_add_notice( sprintf( _n( '%s is a required field', '%s are required fields', sizeof( $missing_attributes ), 'woocommerce' ), wc_format_list_of_items( $missing_attributes ) ), 'error' );
} elseif ( empty( $variation_id ) ) {
wc_add_notice( __( 'Please choose product options…', 'woocommerce' ), 'error' );
} else {
// Add to cart validation
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations );
if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations ) !== false ) {
wc_add_to_cart_message( $product_id );
return true;
}
}
return false;
}
The error is caught in the elseif clause.
So I tried to echo out $variation_id, $variations, and $variation. None of them has anything in it because when I echo $variation_id: it doesn't output anything.
How can the error be resolved?
On shop page you can't use add-to-cart button for variable products, because you need first to go on single product page to chose the options for this variable product before adding it to cart.
On variable product pages, normally you have some displayed options to chose for a variable product, before using "add to cart" button. If you don't do it, you get the error message… So at this point:
The options are not displayed in the product page (Bad settings in your backend product page, a bug with your theme or some additional plugin):
Check your product backend settings
Try to switch to default wordpress theme (to see if this issue is still there)
Try to disable most of all plugins.
the options are displayed: So chose your options first for this product, then add to cart
If this issue is related to your theme, contact the author of your theme and open a support thread or ticket…
OUPUTTING PRODUCT VARIATIONS FOR A PRODUCT ID:
To get product variations programmatically for a variable product ID:
$product = wc_get_product( $product_id );
$product_variations = $product->get_available_variations();
echo var_dump($product_variations); // Displaying the array
Then to get the first variation ID:
$product = wc_get_product( $product_id );
$product_variations = $product->get_available_variations();
$variation_product_id = $product_variations [0]['variation_id'];
echo $variation_product_id; // Displaying the variation ID
Or to get an array of all variations ID of this product ID:
$product = wc_get_product( $product_id );
$product_variations = $product->get_available_variations();
$arr_variations_id = array();
foreach ($product_variations as $variation) {
$product_variation_id = $variation['variation_id'];
array_push( $arr_variations_id, $product_variation_id );
}
echo var_dump($arr_variations_id); // Displaying the array of variations ID
A reference : Change "Add to Cart" button to "Go to Product" in the Shop Page
Just in case anyone else is building a custom theme and encounters this issue with variations not adding to the cart as expected - you may need to check your theme is loading the /woocommerce/assets/js/frontend/add-to-cart-variation.min.js script - add the following to wherever you enqueue your scripts to manually add it:
wp_enqueue_script('wc-add-to-cart-variation');
This solved the issue for me.
While we all have variation swatches in common the error (bizarre as this sounds) lays with the theme being incompatible. To test simply switch to 2020 theme and the ordering should work. I would recommend then making 2020 suite your needs and stop using the theme where the developers take days off when woocommerce updates are rolled out! Disabling the swatches wont help as the code is already there. Good luck.
I was facing the same issue.....delete your variation swatches plugin and the problem will be solved
Had the same issue....deactivated the autoptimize plugin and the problem was solved.
Also,to know which plugin to disable, you can simply load the page or the website, inspect element or developers mode, then check the console to see the source of the error which you can then relate to the relevant plugin and then disable from your wp dashboard.
I use wishlist plugin and when I tried to add variable product to cart I have got: 'The selected product isn't a variation of Product name, please choose product options by visiting Product name.'
The problem was that my product haven't default variation. So user added to wishlist product without selected variation. So when after user tries to add this product to cart error appears.
Here is FIX: just set default variation to all cariation products!
(Manually or via code). So user COULD NOT add product with EMPTY variation. Variation will be selected by default or user changes variation by himself.
So now in wishlist we have variation selected and all works as it should. It will work on all pages, archives, wishlists etc. Good luck! ;)
you’ll need to modify the functions.php file. Simply go to wp-content/yourtheme/functions.php on your child theme. Here, we’ll show you the full code and then we’ll explain its main parts. So the full PHP script to create WooCommerce default product attributes programmatically is the following:
add_action('woocommerce_before_single_product_summary', 'quadlayers_product_default_attributes');
function quadlayers_product_default_attributes() {
global $product;
if (!count($default_attributes = get_post_meta($product->get_id(), '_default_attributes'))) {
$new_defaults = array();
$product_attributes = $product->get_attributes();
if (count($product_attributes)) {
foreach ($product_attributes as $key => $attributes) {
$values = explode(',', $product->get_attribute($key));
if (isset($values[0]) && !isset($default_attributes[$key])) {
$new_defaults[$key] = sanitize_key($values[0]);
}
}
update_post_meta($product->get_id(), '_default_attributes', $new_defaults);
}
}
}

Categories