Commit 3fb02078e0a for woocommerce
commit 3fb02078e0a0f7b85bcf1d97d59cd8f91420e675
Author: Vladimir Reznichenko <kalessil@gmail.com>
Date: Thu Jul 23 06:00:07 2026 +0200
[Performance] Address edge-case concerns reported by an AI after merging #66675. (#66810)
diff --git a/plugins/woocommerce/includes/class-wc-product-variable.php b/plugins/woocommerce/includes/class-wc-product-variable.php
index 2dd266c1d73..cba96f39486 100644
--- a/plugins/woocommerce/includes/class-wc-product-variable.php
+++ b/plugins/woocommerce/includes/class-wc-product-variable.php
@@ -111,6 +111,9 @@ class WC_Product_Variable extends WC_Product {
public function get_variation_prices( $for_display = false ) {
/** @var array<string,array<int,float>> $prices */ // phpcs:ignore Generic.Commenting.DocComment.MissingShort
$prices = $this->data_store->read_price_data( $this, $for_display );
+ if ( ! is_array( $prices ) ) {
+ return $prices;
+ }
// Performance note: loose != compares key/value pairs regardless of order, so a re-sort is only triggered when prices actually change.
$cache_key = $for_display ? 'for_display:1' : 'for_display:0';
diff --git a/plugins/woocommerce/tests/php/includes/class-wc-product-variable-test.php b/plugins/woocommerce/tests/php/includes/class-wc-product-variable-test.php
index d1895097255..d1fbef9739d 100644
--- a/plugins/woocommerce/tests/php/includes/class-wc-product-variable-test.php
+++ b/plugins/woocommerce/tests/php/includes/class-wc-product-variable-test.php
@@ -408,6 +408,45 @@ class WC_Product_Variable_Test extends \WC_Unit_Test_Case {
$product->delete( true );
}
+ /**
+ * @testdox get_variation_prices returns a valid array structure when the woocommerce_variation_prices filter returns malformed data (null or false), restoring the pre-refactor foreach behaviour that tolerated non-array filter output.
+ * @dataProvider provider_malformed_variation_prices_filter_values
+ *
+ * @param mixed $malformed_value The malformed value for returning via woocommerce_get_variation_prices_hash filter.
+ */
+ public function test_get_variation_prices_tolerates_malformed_filter_output( $malformed_value ): void {
+ $product = WC_Helper_Product::create_variation_product();
+
+ // Bust the transient so read_price_data() always reaches the woocommerce_variation_prices filter.
+ $invalidate_cache = static fn( array $hash ) => array( ...$hash, wp_rand() );
+ add_filter( 'woocommerce_get_variation_prices_hash', $invalidate_cache );
+
+ $bad_filter = static fn() => $malformed_value;
+ add_filter( 'woocommerce_variation_prices', $bad_filter );
+
+ try {
+ $prices = $product->get_variation_prices();
+ $this->assertSame( $malformed_value, $prices );
+ } finally {
+ remove_filter( 'woocommerce_variation_prices', $bad_filter );
+ remove_filter( 'woocommerce_get_variation_prices_hash', $invalidate_cache );
+ }
+
+ $product->delete( true );
+ }
+
+ /**
+ * @return array<string,array>
+ */
+ public function provider_malformed_variation_prices_filter_values(): array {
+ return array(
+ 'null' => array( null ),
+ 'false' => array( false ),
+ 'string' => array( 'bad_return' ),
+ 'object' => array( new stdClass() ),
+ );
+ }
+
/**
* Create a real image attachment that passes `wp_attachment_is_image()`.
*