WooCommerce - Empty Cart on Page Reload - php

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;
}

Related

Woocommerce: redirect hook overruled by error

In Wordpress/Woocommerce when clicking an order button, I would like it to skip the basket and immediately go to checkout. To this end, I implemented the following hook:
add_filter('add_to_cart_redirect', 'cw_redirect_add_to_cart');
function cw_redirect_add_to_cart() {
global $woocommerce;
$cw_redirect_url_checkout = $woocommerce->cart->get_checkout_url();
return $cw_redirect_url_checkout;
}
This works. However, in the scenario that the user already has the product in their basket and clicks on the order button, this would normally produce an error message "You cannot add another productname to your basket", which would be displayed on the basket page. But with the code snippet, in this scenario it just refreshes the page where the user clicked the order button and nothing happens. A user will not understand why the button doesn't work (only if they would manually type in the basket url, they will see the error message).
How, in this scenario, can I still redirect to the checkout page?
The hook add_to_cart_redirect you are using is deprecated from version 3.0.0 as the get_checkout_url method is deprecated from version 2.5.
The updated function can be found here: Woocommerce add to cart button redirect to checkout
Your problem is related to the woocommerce_add_to_cart_redirect hook not being executed in case there are any error notices. Below you will find the part of the code extracted from the WooCommerce source code:
// If we added the product to the cart we can now optionally do a redirect.
if ( $was_added_to_cart && 0 === wc_notice_count( 'error' ) ) {
$url = apply_filters( 'woocommerce_add_to_cart_redirect', $url, $adding_to_cart );
if ( $url ) {
wp_safe_redirect( $url );
exit;
} elseif ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add' ) ) {
wp_safe_redirect( wc_get_cart_url() );
exit;
}
}
So to fix the problem you can find a solution here.The post includes a Fix for "Sold Individually" Products section that answers your question.

On cart items stock issue disable WooCommerce Place order checkout button

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.
}

Sending Two Simple Product To Add To Cart In Single Woocommerce Button Click

I am adding two different products in my website and they both combines together to form one single product, what i am trying to achieve is that when i click on the add to cart button, I want to send two product id's to "add to cart" which means two different products, one is the page from where the a"dd to cart" is clicked and the second one is manual product id which i've assigned to hidden text box.
I tried the ajax call but that didn't work. Also I don't want to go with woocommerce paid extensions for bundle products and other types.
So it would be great if i can make some changes to add to cart.
Try something simple, like "Woocommerce Free Gift" plugin, there is a free version as well. You can setup automatic product add to cart on certain circumstances.
Otherwise, you need to modify your functions.php, whenever you are adding "product A" -> add "product B". Something likes this:
add_action( 'init', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
global $woocommerce;
$product_id = ID_OF_PRODUCT_A;
$product_b = ID_OF_PRODUCT_B;
$found = false;
if( $woocommerce->cart->total > 0 ) {
//check if product already in cart
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( $found )
$woocommerce->cart->add_to_cart( $product_b );
} else {
// do something
}
}
}
}

WooCommerce check cart contents on add to cart

I only have one product to display, but I offer two options for it: A payment plan (handled through a subscription plugin) and a single payment. I have them displayed on my site as a grouped and both options have an "Add to Cart" Button. I don't want either option to be in the cart at the same time as the other. What I would like to do is either,
A) Empty the cart before each time the add to cart is clicked.
or
B) Check if the cart contains a product already (via productid), and remove the payment plan if the full pay is selected, or vice versa. Here is something I've come up with for this option, but I'm a bit lost and it's not functioning quite right.
global $woocommerce;
if ($product_id = 66){
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $cart_item ) {
echo $cart_item_key;
if($cart_item['product_id'] == '69'){
//remove single product
$woocommerce->cart->remove_cart_item($cart_item_key);
}
}
}
elseif ($product_id = 69){
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $cart_item ) {
echo $cart_item_key;
if($cart_item['product_id'] == '66'){
//remove single product
$woocommerce->cart->remove_cart_item($cart_item_key);
}
}
}
I'm thinking of adding this to the add_to_cart method before the try/catch to throw any errors. Can anyone help me figure a better solution?
Emptying the cart would be very easy
add_filter( 'woocommerce_add_to_cart_validation', 'so_31392001_empty_cart', 10, 3 );
function so_31392001_empty_cart( $valid, $product_id, $quantity ) {
WC()->cart->empty_cart();
return $valid;
}

Woocommerce: Programmatically Update Item In Cart

I need to programmatically and dynamically change the price of an item in the cart.
I’ve tried varying combinations of Woocommerce action hooks, the cart and session objects, but nothing quite seems to do the trick. I thought this wouldn’t be so challenging.
add_action( 'woocommerce_before_calculate_totals', 'change_cart_item_price' );
function change_cart_item_price( $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
if( 123 == $value['data']->id ) {
$new_price = function_to_get_new_price( $value, get_current_user_id( ) );
$value['data']->price = $new_price;
}
}
}
The above code changes the price for each item only on the checkout page, or when updating the cart (ie: the hook is called when removing an item from the cart), but not indefinitely.
I'm using the Woocommerce Gravity Forms add-on. I have one product in particular, which will be ordered multiple times by a given user. The user will be allowed 5x free with only shipping fees, and each above 5 will be $20. I have this much coded and functional with Gravity Forms hooks that dynamically populate fields. Shipping is specific to fields within the gravity form, therefore I am leaving that calculation to Gravity Forms.
My issue is that if a user reduces the quantity of this product from their order (removes one of the items from the cart), it should re-calculate the price of each item of the same product within the cart, otherwise they could be over-charged (an item that used to be the 6th is now the 4th, but the price remains the same, which it shouldn't)
Therefore, I would like to re-calculate the price of each item in the cart, based on the quantity of this particular product, every time something is removed from the cart.
--- EDIT ---
The above code works, but I'm realizing the issue must be a custom loop I'm using to display the prices...
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = $cart_item['data'];
if( 123 == $_product->post->ID ) {
$price_not_updated = $cart_item['data']->price;
}
}
I figured it out... I looked at the woocommerce cart docs and essentially realized that the prices I was getting had yet to be calculated. So, before running the loop, I had to do the action that I was initially hooking into to change the prices.
Thanks for your help!
function getUpdatedCartPrices() {
do_action( 'woocommerce_before_calculate_totals', WC()->cart );
$horray_updated_prices_works = array();
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = $cart_item['data'];
if( 123 == $_product->post->ID ) {
$horray_updated_prices_works[] = $cart_item['data']->price;
}
}
}
I changed the function to have a second parameter so that you can use it dynamically with any product as long as you call the proper id. I also set the function return value to either a success or error message. This way you can know if it was changed, and if so, to what price. Hope this helps.
by the way, having this function called again when the cart is updated should solve the recalculation issue. It would be great if i could see the code for your $function_to_get_new_price() function.
add_action( 'woocommerce_before_calculate_totals', 'change_cart_item_price' );
function change_cart_item_price($id, $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
if( $id == $value['data']->id ) {
$new_price = function_to_get_new_price( $value, get_current_user_id( ) );
$value['data']->price = $new_price;
$successMsg = "The price of item $value['data']->id was set to $value['data']->price".;
return $successMsg;
}else{
$errorMsg = "Price was not changed!";
return $errorMsg;
}
}
}

Categories