Commit d2ded717f4a for woocommerce

commit d2ded717f4aaaf50d3fd765aa6154dbfd6e1de41
Author: Jorge A. Torres <jorge.torres@automattic.com>
Date:   Thu Jul 2 18:42:58 2026 +0100

    Warn when an order status key is too long to store (#66164)

diff --git a/plugins/woocommerce/changelog/54584-fix-order-status-key-length b/plugins/woocommerce/changelog/54584-fix-order-status-key-length
new file mode 100644
index 00000000000..3e0ce663f64
--- /dev/null
+++ b/plugins/woocommerce/changelog/54584-fix-order-status-key-length
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Warn when an order status key is too long and can't be stored.
diff --git a/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php b/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php
index 3aa743bb319..4d0770c2caa 100644
--- a/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php
+++ b/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php
@@ -378,6 +378,18 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
 			$post_status = 'wc-' . $post_status;
 		}

+		// The status column holds at most 20 characters, so a longer key can't be stored.
+		if ( strlen( $post_status ) > 20 ) {
+			wc_doing_it_wrong(
+				__METHOD__,
+				sprintf(
+					'Order status "%s" is longer than the storage limit of 20 characters and cannot be stored.',
+					esc_html( $order_status )
+				),
+				'11.0.0'
+			);
+		}
+
 		return $post_status;
 	}

diff --git a/plugins/woocommerce/tests/php/includes/abstracts/class-wc-abstract-order-test.php b/plugins/woocommerce/tests/php/includes/abstracts/class-wc-abstract-order-test.php
index ef6dfb13ce5..b9370e0cfa0 100644
--- a/plugins/woocommerce/tests/php/includes/abstracts/class-wc-abstract-order-test.php
+++ b/plugins/woocommerce/tests/php/includes/abstracts/class-wc-abstract-order-test.php
@@ -17,10 +17,23 @@ class WC_Abstract_Order_Test extends WC_Unit_Test_Case {

 	use CogsAwareUnitTestSuiteTrait;

+	/**
+	 * Post statuses registered during a test, to clean up on tear down.
+	 *
+	 * @var string[]
+	 */
+	private $registered_order_statuses = array();
+
 	/**
 	 * Runs after each test.
 	 */
 	public function tearDown(): void {
+		// register_post_status() mutates the global registry, which WP_UnitTestCase does not restore.
+		foreach ( $this->registered_order_statuses as $status ) {
+			unset( $GLOBALS['wp_post_statuses'][ $status ] );
+		}
+		$this->registered_order_statuses = array();
+
 		parent::tearDown();
 		$this->disable_cogs_feature();
 	}
@@ -995,4 +1008,56 @@ class WC_Abstract_Order_Test extends WC_Unit_Test_Case {
 			remove_filter( 'woocommerce_order_type_to_group', $adjust );
 		}
 	}
+
+	/**
+	 * Register a custom order status so it survives set_status() and is prefixed on save.
+	 *
+	 * Registers it in the valid order statuses (so set_status keeps it) and as a post status
+	 * (so get_post_status adds the wc- prefix, which is what pushes it over the column limit).
+	 *
+	 * @param string $status Unprefixed order status key.
+	 */
+	private function register_custom_order_status( string $status ): void {
+		$prefixed = 'wc-' . $status;
+
+		add_filter(
+			'wc_order_statuses',
+			function ( $statuses ) use ( $prefixed ) {
+				$statuses[ $prefixed ] = 'Custom status for testing';
+				return $statuses;
+			}
+		);
+		register_post_status( $prefixed );
+		$this->registered_order_statuses[] = $prefixed;
+	}
+
+	/**
+	 * @testdox Should warn when an order is saved with a status that exceeds the storage limit.
+	 */
+	public function test_saving_an_order_with_a_too_long_status_warns() {
+		$this->setExpectedIncorrectUsage( 'Abstract_WC_Order_Data_Store_CPT::get_post_status' );
+
+		// 'wc-' + 18 characters = 21, one over the 20-character storage limit.
+		$status = str_repeat( 'a', 18 );
+		$this->register_custom_order_status( $status );
+
+		$order = WC_Helper_Order::create_order();
+		$order->set_status( $status );
+		$order->save();
+	}
+
+	/**
+	 * @testdox Should not warn when an order is saved with a status at the storage limit.
+	 */
+	public function test_saving_an_order_with_a_status_at_the_limit_does_not_warn() {
+		// 'wc-' + 17 characters = 20, exactly the storage limit.
+		$status = str_repeat( 'a', 17 );
+		$this->register_custom_order_status( $status );
+
+		$order = WC_Helper_Order::create_order();
+		$order->set_status( $status );
+		$order->save();
+
+		$this->assertSame( $status, wc_get_order( $order->get_id() )->get_status() );
+	}
 }