diff --git a/includes/widgets/class-wc-widget-layered-nav.php b/includes/widgets/class-wc-widget-layered-nav.php index 812dede9c1f..41568504f42 100644 --- a/includes/widgets/class-wc-widget-layered-nav.php +++ b/includes/widgets/class-wc-widget-layered-nav.php @@ -368,7 +368,7 @@ class WC_Widget_Layered_Nav extends WC_Widget { // Generate the first part of the query. // This one will return non-variable products and variable products with concrete values for the attributes. $query = array(); - $query['select'] = "SELECT IF({$wpdb->posts}.post_type='variable_product', {$wpdb->posts}.post_parent, {$wpdb->posts}.ID) AS product_id, terms.term_id AS term_count_id"; + $query['select'] = "SELECT IF({$wpdb->posts}.post_type='product_variation', {$wpdb->posts}.post_parent, {$wpdb->posts}.ID) AS product_id, terms.term_id AS term_count_id"; $query['from'] = "FROM {$wpdb->posts}"; $query['join'] = " INNER JOIN {$wpdb->term_relationships} AS tr ON {$wpdb->posts}.ID = tr.object_id @@ -417,17 +417,16 @@ class WC_Widget_Layered_Nav extends WC_Widget { // This one will return products having "Any..." as the value of the attribute. $query_sql_for_attributes_with_any_value = " - SELECT {$wpdb->posts}.post_parent AS product_id, {$wpdb->term_relationships}.term_taxonomy_id as term_count_id FROM {$wpdb->posts} - LEFT JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = 'attribute_$taxonomy' - JOIN {$wpdb->term_relationships} ON {$wpdb->term_relationships}.object_id = {$wpdb->posts}.post_parent + SELECT {$wpdb->posts}.ID AS product_id, {$wpdb->term_relationships}.term_taxonomy_id as term_count_id FROM {$wpdb->posts} + JOIN {$wpdb->posts} variations ON variations.post_parent = {$wpdb->posts}.ID + LEFT JOIN {$wpdb->postmeta} ON variations.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = 'attribute_$taxonomy' + JOIN {$wpdb->term_relationships} ON {$wpdb->term_relationships}.object_id = {$wpdb->posts}.ID WHERE ( {$wpdb->postmeta}.meta_key IS NULL OR {$wpdb->postmeta}.meta_value = '') - AND {$wpdb->posts}.post_type = 'product_variation' + AND {$wpdb->posts}.post_type = 'product' AND {$wpdb->posts}.post_status = 'publish' + AND variations.post_status = 'publish' + AND variations.post_type = 'product_variation' AND {$wpdb->term_relationships}.term_taxonomy_id in $term_ids_sql - AND NOT EXISTS ( - SELECT ID FROM {$wpdb->posts} AS parent - WHERE parent.ID = {$wpdb->posts}.post_parent AND parent.post_status NOT IN ('publish') - ) {$main_tax_query_sql['where']}"; // We have two queries - let's see if cached results of this query already exist. @@ -455,38 +454,25 @@ class WC_Widget_Layered_Nav extends WC_Widget { /** * Get the count of terms for products, using a set of SQL queries that are return pairs of product id - term id. * - * @param string ...$queries SQL queries to use, each must return a "product_id" column and a "terms_count_id" column. + * @param string $main_query_sql The SQL query to use in order to count products with concrete values for attributes, must return a "product_id" column and a "terms_count_id" column. + * @param string $query_sql_for_attributes_with_any_value The SQL query to use in order to count products with "Any" values for attributes, must return a "product_id" column and a "terms_count_id" column. * * @return array An array where the keys are term ids, and the values are term counts. */ - private function get_term_product_counts_from_queries( ...$queries ) { + private function get_term_product_counts_from_queries( $main_query_sql, $query_sql_for_attributes_with_any_value ) { global $wpdb; $total_counts = null; - foreach ( $queries as $query ) { - $query = " + $query = " SELECT COUNT(DISTINCT(product_id)) AS term_count, term_count_id FROM ( - {$query} + {$main_query_sql} + UNION ALL + {$query_sql_for_attributes_with_any_value} ) AS x GROUP BY term_count_id"; - $results = $wpdb->get_results( $query, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared - $counts = array_map( 'absint', wp_list_pluck( $results, 'term_count', 'term_count_id' ) ); - - if ( is_null( $total_counts ) ) { - $total_counts = $counts; - } else { - foreach ( $counts as $term_id => $term_count ) { - if ( array_key_exists( $term_id, $total_counts ) ) { - $total_counts[ $term_id ] += $term_count; - } else { - $total_counts[ $term_id ] = $term_count; - } - } - } - } - - return $total_counts; + $results = $wpdb->get_results( $query, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + return array_map( 'absint', wp_list_pluck( $results, 'term_count', 'term_count_id' ) ); } /** diff --git a/tests/unit-tests/widgets/class-wc-tests-widget-layered-nav.php b/tests/unit-tests/widgets/class-wc-tests-widget-layered-nav.php index 156f231178c..a1ebc606d7d 100644 --- a/tests/unit-tests/widgets/class-wc-tests-widget-layered-nav.php +++ b/tests/unit-tests/widgets/class-wc-tests-widget-layered-nav.php @@ -519,7 +519,6 @@ class WC_Tests_Widget_Layered_Nav extends WC_Unit_Test_Case { $variation_objects = array(); foreach ( $existing_styles as $style ) { $variation_attributes = array( - 'pa_color' => '', 'pa_style' => $style, ); $variation_object = WC_Helper_Product::create_product_variation_object( @@ -547,6 +546,7 @@ class WC_Tests_Widget_Layered_Nav extends WC_Unit_Test_Case { } $main_product->set_children( $variation_objects ); + $main_product->save(); return $main_product; }