Merge pull request #27589 from woocommerce/enhance-query-for-filtering-attributes-with-any-value

Enhance the query for "Any" variations in filter by attribute widget
This commit is contained in:
jonathansadowski 2020-09-08 11:58:54 -05:00 committed by GitHub
commit 168698cd91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 32 deletions

View File

@ -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' ) );
}
/**

View File

@ -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;
}