Commit bf821507aa7 for woocommerce

commit bf821507aa7193e8465548e8fbe67401daf919ba
Author: Mike Jolley <mike.jolley@me.com>
Date:   Thu Jul 2 10:06:33 2026 +0100

    Fix stock reservation default duration (#66048)

diff --git a/plugins/woocommerce/changelog/fix-30612-stock-reservation-default b/plugins/woocommerce/changelog/fix-30612-stock-reservation-default
new file mode 100644
index 00000000000..daa06424748
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-30612-stock-reservation-default
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Use the checkout hold stock setting only for core checkout stock reservations.
diff --git a/plugins/woocommerce/includes/wc-stock-functions.php b/plugins/woocommerce/includes/wc-stock-functions.php
index 9afd29f5f83..29b6c709df0 100644
--- a/plugins/woocommerce/includes/wc-stock-functions.php
+++ b/plugins/woocommerce/includes/wc-stock-functions.php
@@ -453,7 +453,7 @@ function wc_reserve_stock_for_order( $order ) {

 	if ( $order ) {
 		$reserve_stock = new ReserveStock();
-		$reserve_stock->reserve_stock_for_order( $order );
+		$reserve_stock->reserve_stock_for_order( $order, (int) get_option( 'woocommerce_hold_stock_minutes', 60 ) );
 	}
 }
 add_action( 'woocommerce_checkout_order_created', 'wc_reserve_stock_for_order' );
diff --git a/plugins/woocommerce/src/Checkout/Helpers/ReserveStock.php b/plugins/woocommerce/src/Checkout/Helpers/ReserveStock.php
index c884e66c04b..3ecf85a47bf 100644
--- a/plugins/woocommerce/src/Checkout/Helpers/ReserveStock.php
+++ b/plugins/woocommerce/src/Checkout/Helpers/ReserveStock.php
@@ -68,14 +68,13 @@ final class ReserveStock {
 	 * @throws ReserveStockException If stock cannot be reserved.
 	 *
 	 * @param \WC_Order $order Order object.
-	 * @param int       $minutes How long to reserve stock in minutes. Defaults to woocommerce_hold_stock_minutes.
+	 * @param int       $minutes How long to reserve stock in minutes. Defaults to 60.
 	 */
-	public function reserve_stock_for_order( $order, $minutes = 0 ) {
+	public function reserve_stock_for_order( $order, $minutes = 60 ) {
 		if ( ! $this->is_enabled() ) {
 			return;
 		}

-		$minutes = $minutes ? $minutes : (int) get_option( 'woocommerce_hold_stock_minutes', 60 );
 		/**
 		 * Filters the number of minutes an order should reserve stock for.
 		 *
@@ -83,7 +82,7 @@ final class ReserveStock {
 		 *
 		 * @since 8.8.0
 		 *
-		 * @param int       $minutes How long to reserve stock for the order in minutes. Defaults to woocommerce_hold_stock_minutes or 10 if block checkout entry.
+		 * @param int       $minutes How long to reserve stock for the order in minutes.
 		 * @param \WC_Order $order Order object.
 		 */
 		$minutes = (int) apply_filters( 'woocommerce_order_hold_stock_minutes', $minutes, $order );
diff --git a/plugins/woocommerce/tests/php/includes/wc-stock-functions-tests.php b/plugins/woocommerce/tests/php/includes/wc-stock-functions-tests.php
index 1453d340e97..7d1e073c773 100644
--- a/plugins/woocommerce/tests/php/includes/wc-stock-functions-tests.php
+++ b/plugins/woocommerce/tests/php/includes/wc-stock-functions-tests.php
@@ -5,6 +5,7 @@
  * @package WooCommerce\Tests\Functions\Stock
  */

+use Automattic\WooCommerce\Checkout\Helpers\ReserveStock;
 use Automattic\WooCommerce\Enums\OrderInternalStatus;

 /**
@@ -70,6 +71,71 @@ class WC_Stock_Functions_Tests extends \WC_Unit_Test_Case {
 		return $order;
 	}

+	/**
+	 * Run a callback with stock reservation enabled and the configured hold duration.
+	 *
+	 * @param string   $hold_stock_minutes Configured hold stock duration.
+	 * @param callable $callback Callback to run.
+	 * @return mixed
+	 */
+	private function with_stock_reservation_options( $hold_stock_minutes, $callback ) {
+		$option_names         = array(
+			'woocommerce_hold_stock_minutes',
+			'woocommerce_manage_stock',
+			'woocommerce_schema_version',
+		);
+		$missing_option_value = new stdClass();
+		$original_options     = array();
+
+		foreach ( $option_names as $option_name ) {
+			$option_value                     = get_option( $option_name, $missing_option_value );
+			$original_options[ $option_name ] = array(
+				'exists' => $missing_option_value !== $option_value,
+				'value'  => $option_value,
+			);
+		}
+
+		update_option( 'woocommerce_hold_stock_minutes', $hold_stock_minutes );
+		update_option( 'woocommerce_manage_stock', 'yes' );
+		update_option( 'woocommerce_schema_version', 430 );
+
+		try {
+			return $callback();
+		} finally {
+			foreach ( $original_options as $option_name => $option_data ) {
+				if ( $option_data['exists'] ) {
+					update_option( $option_name, $option_data['value'] );
+				} else {
+					delete_option( $option_name );
+				}
+			}
+		}
+	}
+
+	/**
+	 * Capture stock reservation minutes observed by the stock hold filter.
+	 *
+	 * @param callable $reserve_stock_callback Callback that attempts to reserve stock.
+	 * @return int|null
+	 */
+	private function get_captured_order_hold_stock_minutes( $reserve_stock_callback ) {
+		$captured_minutes = null;
+		$capture_minutes  = function ( $minutes ) use ( &$captured_minutes ) {
+			$captured_minutes = $minutes;
+			return 0;
+		};
+
+		add_filter( 'woocommerce_order_hold_stock_minutes', $capture_minutes );
+
+		try {
+			$reserve_stock_callback();
+		} finally {
+			remove_filter( 'woocommerce_order_hold_stock_minutes', $capture_minutes );
+		}
+
+		return $captured_minutes;
+	}
+
 	/**
 	 * Helper function to change order status and assert product inventory values.
 	 *
@@ -213,6 +279,55 @@ class WC_Stock_Functions_Tests extends \WC_Unit_Test_Case {
 		self::assertIsInteger( $actual );
 	}

+	/**
+	 * @testdox reserve_stock_for_order defaults to 60 minutes when no duration is provided.
+	 */
+	public function test_reserve_stock_for_order_defaults_to_60_minutes() {
+		$minutes = $this->with_stock_reservation_options(
+			'15',
+			function () {
+				$order         = wc_create_order();
+				$reserve_stock = new ReserveStock();
+
+				return $this->get_captured_order_hold_stock_minutes(
+					function () use ( $reserve_stock, $order ) {
+						$reserve_stock->reserve_stock_for_order( $order );
+					}
+				);
+			}
+		);
+
+		$this->assertSame(
+			60,
+			$minutes,
+			'Direct stock reservation calls should use the explicit default duration.'
+		);
+	}
+
+	/**
+	 * @testdox wc_reserve_stock_for_order passes the configured checkout stock hold duration.
+	 */
+	public function test_wc_reserve_stock_for_order_passes_configured_checkout_hold_duration() {
+		$minutes = $this->with_stock_reservation_options(
+			'15',
+			function () {
+				$order = wc_create_order();
+
+				return $this->get_captured_order_hold_stock_minutes(
+					function () use ( $order ) {
+						wc_reserve_stock_for_order( $order );
+					}
+				);
+			}
+		);
+
+		$this->assertSame(
+			15,
+			$minutes,
+			'Core checkout stock reservation should use the configured hold duration.'
+		);
+	}
+
 	/**
 	 * Test wc_get_low_stock_amount with a simple product which has low stock amount set.
 	 */