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.
*/