Commit 51c5dce4759 for woocommerce
commit 51c5dce475999611bd15bfeb3d03b7d4e48d629d
Author: Darren Ethier <darren@roughsmootheng.in>
Date: Wed Aug 19 07:36:56 2026 -0400
Fix Recently Viewed Products widget query cap (#67825)
diff --git a/plugins/woocommerce/changelog/fix-recently-viewed-widget-query-cap b/plugins/woocommerce/changelog/fix-recently-viewed-widget-query-cap
new file mode 100644
index 00000000000..d90d1fdccd3
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-recently-viewed-widget-query-cap
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Limit the Recently Viewed Products widget query to the 15 most recent product IDs from the cookie. This prevents oversized cookies from increasing query workload while preserving normal browsing behavior.
diff --git a/plugins/woocommerce/includes/widgets/class-wc-widget-recently-viewed.php b/plugins/woocommerce/includes/widgets/class-wc-widget-recently-viewed.php
index b957fe6b3e7..69619f519fc 100644
--- a/plugins/woocommerce/includes/widgets/class-wc-widget-recently-viewed.php
+++ b/plugins/woocommerce/includes/widgets/class-wc-widget-recently-viewed.php
@@ -51,7 +51,7 @@ class WC_Widget_Recently_Viewed extends WC_Widget {
*/
public function widget( $args, $instance ) {
$viewed_products = ! empty( $_COOKIE['woocommerce_recently_viewed'] ) ? (array) explode( '|', wp_unslash( $_COOKIE['woocommerce_recently_viewed'] ) ) : array(); // @codingStandardsIgnoreLine
- $viewed_products = array_reverse( array_filter( array_map( 'absint', $viewed_products ) ) );
+ $viewed_products = array_slice( array_reverse( array_filter( array_map( 'absint', $viewed_products ) ) ), 0, 15 );
if ( empty( $viewed_products ) ) {
return;
@@ -71,14 +71,14 @@ class WC_Widget_Recently_Viewed extends WC_Widget {
);
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
- $query_args['tax_query'] = array(
+ $query_args['tax_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Recently viewed product IDs are capped at 15.
array(
'taxonomy' => 'product_visibility',
'field' => 'name',
'terms' => ProductStockStatus::OUT_OF_STOCK,
'operator' => 'NOT IN',
),
- ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query -- The taxonomy filter is bounded to the non-empty recently viewed product ID list.
+ );
}
$r = new WP_Query( apply_filters( 'woocommerce_recently_viewed_products_widget_query_args', $query_args ) );
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/widgets/class-wc-tests-widget.php b/plugins/woocommerce/tests/legacy/unit-tests/widgets/class-wc-tests-widget.php
index aca4f33fb29..c5b610ba77f 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/widgets/class-wc-tests-widget.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/widgets/class-wc-tests-widget.php
@@ -64,4 +64,42 @@ class WC_Tests_Widget extends WC_Unit_Test_Case {
$dummy_widget = $wp_widget_factory->widgets['Dummy_Widget'];
$this->assertEmpty( $dummy_widget->form( array( 'widget_id' => $dummy_widget->widget_id ) ) );
}
+
+ /**
+ * @testdox Should limit recently viewed widget queries from oversized cookies.
+ */
+ public function test_recently_viewed_widget_query_limits_oversized_cookie(): void {
+ $viewed_product_ids = range( 1, 20 );
+ $query_args = array();
+ $query_args_filter = static function ( $args ) use ( &$query_args ) {
+ $query_args = $args;
+
+ return $args;
+ };
+ $cookies = $_COOKIE; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Preserve global test cookie state.
+
+ $_COOKIE['woocommerce_recently_viewed'] = implode( '|', $viewed_product_ids );
+ add_filter( 'woocommerce_recently_viewed_products_widget_query_args', $query_args_filter );
+
+ try {
+ $widget = new WC_Widget_Recently_Viewed();
+
+ ob_start();
+ try {
+ $widget->widget( array(), array() );
+ } finally {
+ ob_end_clean();
+ }
+
+ $this->assertSame(
+ array_slice( array_reverse( $viewed_product_ids ), 0, 15 ),
+ $query_args['post__in'],
+ 'An oversized recently viewed cookie should only send the 15 newest product IDs to the query.'
+ );
+ } finally {
+ remove_filter( 'woocommerce_recently_viewed_products_widget_query_args', $query_args_filter );
+
+ $_COOKIE = $cookies;
+ }
+ }
}