Fix emptying cart issue for custom order statuses (#44515)

* fix: add filter for pre payment order statuses

* chore: resolve linting issue

* chore: remove comment

* chore: add filter comment block

* chore: resolve linting issue

* fix: replace pre payment status filter with clear cart boolean filter

* chore: resolve linting issue

* refactor: remove double negation in check

Co-authored-by: Leif Singer <github.2017@singer.sh>

* tweak changelog message

* rename changelog file

* tweak changelog format

* fix: rework wc_clear_cart_after_payment to clear the cart at the end

* fix: remove order as param for clear cart after payment filter

* Linting/whitespace.

* fix: add after payment flag to prevent calling filter unnecessarily

---------

Co-authored-by: Leif Singer <github.2017@singer.sh>
Co-authored-by: Barry Hughes <3594411+barryhughes@users.noreply.github.com>
This commit is contained in:
Alex Jones 2024-08-09 20:18:21 +01:00 committed by GitHub
parent c8c8a6a56d
commit cc9d558a31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 6 deletions

View File

@ -0,0 +1,5 @@
Significance: patch
Type: tweak
Add the `woocommerce_should_clear_cart_after_payment` filter to influence whether the cart should be cleared after payment.

View File

@ -170,6 +170,10 @@ function wc_format_list_of_items( $items ) {
function wc_clear_cart_after_payment() { function wc_clear_cart_after_payment() {
global $wp; global $wp;
$should_clear_cart_after_payment = false;
$after_payment = false;
// If the order has been received, clear the cart.
if ( ! empty( $wp->query_vars['order-received'] ) ) { if ( ! empty( $wp->query_vars['order-received'] ) ) {
$order_id = absint( $wp->query_vars['order-received'] ); $order_id = absint( $wp->query_vars['order-received'] );
@ -179,21 +183,39 @@ function wc_clear_cart_after_payment() {
$order = wc_get_order( $order_id ); $order = wc_get_order( $order_id );
if ( $order instanceof WC_Order && hash_equals( $order->get_order_key(), $order_key ) ) { if ( $order instanceof WC_Order && hash_equals( $order->get_order_key(), $order_key ) ) {
WC()->cart->empty_cart(); $should_clear_cart_after_payment = true;
$after_payment = true;
} }
} }
} }
if ( is_object( WC()->session ) && WC()->session->order_awaiting_payment > 0 ) { // If the order is awaiting payment, and we haven't already decided to clear the cart, check the order status.
if ( is_object( WC()->session ) && WC()->session->order_awaiting_payment > 0 && ! $should_clear_cart_after_payment ) {
$order = wc_get_order( WC()->session->order_awaiting_payment ); $order = wc_get_order( WC()->session->order_awaiting_payment );
if ( $order instanceof WC_Order && $order->get_id() > 0 ) { if ( $order instanceof WC_Order && $order->get_id() > 0 ) {
// If the order has not failed, or is not pending, the order must have gone through. // If the order status is neither pending, failed, nor cancelled, the order must have gone through.
if ( ! $order->has_status( array( 'failed', 'pending', 'cancelled' ) ) ) { $should_clear_cart_after_payment = ! $order->has_status( array( 'failed', 'pending', 'cancelled' ) );
WC()->cart->empty_cart(); $after_payment = true;
}
} }
} }
// If it doesn't look like a payment happened, bail early.
if ( ! $after_payment ) {
return;
}
/**
* Determine whether the cart should be cleared after payment.
*
* @since 9.3.0
* @param bool $should_clear_cart_after_payment Whether the cart should be cleared after payment.
*/
$should_clear_cart_after_payment = apply_filters( 'woocommerce_should_clear_cart_after_payment', $should_clear_cart_after_payment );
if ( $should_clear_cart_after_payment ) {
WC()->cart->empty_cart();
}
} }
add_action( 'template_redirect', 'wc_clear_cart_after_payment', 20 ); add_action( 'template_redirect', 'wc_clear_cart_after_payment', 20 );