Automattic\WooCommerce\StoreApi\Utilities

ProductQueryFilters::get_attribute_counts()publicWC 1.0

Get attribute and meta counts.

Method of the class: ProductQueryFilters{}

No Hooks.

Return

Array.

Usage

$ProductQueryFilters = new ProductQueryFilters();
$ProductQueryFilters->get_attribute_counts( $request, $filtered_attribute );
$request(WP_REST_Request) (required)
Request data.
$filtered_attribute(string) (required)
The attribute to count.

ProductQueryFilters::get_attribute_counts() code WC 8.7.0

public function get_attribute_counts( $request, $filtered_attribute ) {
	if ( is_array( $filtered_attribute ) ) {
		wc_deprecated_argument( 'attributes', 'TBD', 'get_attribute_counts does not require an array of attributes as the second parameter anymore. Provide the filtered attribute as a string instead.' );

		$filtered_attribute = ! empty( $filtered_attribute[0] ) ? $filtered_attribute[0] : '';

		if ( empty( $filtered_attribute ) ) {
			return array();
		}
	}

	$attributes_data            = $request->get_param( 'attributes' );
	$calculate_attribute_counts = $request->get_param( 'calculate_attribute_counts' );
	$min_price                  = $request->get_param( 'min_price' );
	$max_price                  = $request->get_param( 'max_price' );
	$rating                     = $request->get_param( 'rating' );
	$stock_status               = $request->get_param( 'stock_status' );

	$transient_key = 'wc_get_attribute_and_meta_counts_' . md5(
		wp_json_encode(
			array(
				'attributes_data'            => $attributes_data,
				'calculate_attribute_counts' => $calculate_attribute_counts,
				'min_price'                  => $min_price,
				'max_price'                  => $max_price,
				'rating'                     => $rating,
				'stock_status'               => $stock_status,
				'filtered_attribute'         => $filtered_attribute,
			)
		)
	);

	$cached_results = get_transient( $transient_key );
	if ( ! empty( $cached_results ) && defined( 'WP_DEBUG' ) && ! WP_DEBUG ) {
		return $cached_results;
	}

	if ( empty( $attributes_data ) && empty( $min_price ) && empty( $max_price ) && empty( $rating ) && empty( $stock_status ) ) {
		$counts = $this->get_terms_list( $filtered_attribute );

		return array_map( 'absint', wp_list_pluck( $counts, 'term_count', 'term_count_id' ) );
	}

	$where_clause = '';
	if ( ! empty( $min_price ) || ! empty( $max_price ) || ! empty( $rating ) || ! empty( $stock_status ) ) {
		$product_metas = [
			'min_price'      => $min_price,
			'max_price'      => $max_price,
			'average_rating' => $rating,
			'stock_status'   => $stock_status,
		];

		$filtered_products_by_metas           = $this->get_product_by_metas( $product_metas );
		$formatted_filtered_products_by_metas = implode( ',', array_map( 'intval', $filtered_products_by_metas ) );

		if ( ! empty( $formatted_filtered_products_by_metas ) ) {
			if ( ! empty( $rating ) ) {
				$where_clause .= sprintf( ' AND product_attribute_lookup.product_or_parent_id IN (%1s)', $formatted_filtered_products_by_metas );
			} else {
				$where_clause .= sprintf( ' AND product_attribute_lookup.product_id IN (%1s)', $formatted_filtered_products_by_metas );
			}
		} else {
			$counts = $this->get_empty_terms_list( $filtered_attribute );

			return array_map( 'absint', wp_list_pluck( $counts, 'term_count', 'term_count_id' ) );
		}
	}

	$join_type = 'LEFT';
	foreach ( $attributes_data as $attribute ) {
		$filtered_terms = $attribute['slug'] ?? '';

		if ( empty( $filtered_terms ) ) {
			continue;
		}

		$taxonomy = $attribute['attribute'] ?? '';
		$term_ids = [];
		if ( in_array( $taxonomy, wc_get_attribute_taxonomy_names(), true ) ) {
			foreach ( $filtered_terms as $filtered_term ) {
				$term = get_term_by( 'slug', $filtered_term, $taxonomy );
				if ( is_object( $term ) ) {
					$term_ids[] = $term->term_id;
				}
			}
		}

		if ( empty( $term_ids ) ) {
			continue;
		}

		foreach ( $calculate_attribute_counts as $calculate_attribute_count ) {
			if ( ! isset( $calculate_attribute_count['taxonomy'] ) && ! isset( $calculate_attribute_count['query_type'] ) ) {
				continue;
			}

			$query_type                           = $calculate_attribute_count['query_type'];
			$filtered_products_by_terms           = $this->get_product_by_filtered_terms( $calculate_attribute_count['taxonomy'], $term_ids, $query_type );
			$formatted_filtered_products_by_terms = implode( ',', array_map( 'intval', $filtered_products_by_terms ) );

			if ( ! empty( $formatted_filtered_products_by_terms ) ) {
				$where_clause .= sprintf( ' AND product_attribute_lookup.product_or_parent_id IN (%1s)', $formatted_filtered_products_by_terms );
			}

			if ( $calculate_attribute_count['taxonomy'] === $filtered_attribute ) {
				$join_type = 'or' === $query_type ? 'LEFT' : 'INNER';
			}
		}
	}

	global $wpdb;
	$counts = $wpdb->get_results(
	// phpcs:disable WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder
		$wpdb->prepare(
			"
			SELECT attributes.term_id as term_count_id, coalesce(term_count, 0) as term_count
			FROM (SELECT DISTINCT term_id
				FROM {$wpdb->prefix}wc_product_attributes_lookup
					WHERE taxonomy = %s) as attributes %1s JOIN (
					SELECT COUNT(DISTINCT product_attribute_lookup.product_or_parent_id) as term_count, product_attribute_lookup.term_id
					FROM {$wpdb->prefix}wc_product_attributes_lookup product_attribute_lookup
						INNER JOIN {$wpdb->posts} posts
							ON posts.ID = product_attribute_lookup.product_id
					WHERE posts.post_type IN ('product', 'product_variation') AND posts.post_status = 'publish'%1s
					GROUP BY product_attribute_lookup.term_id
				) summarize
			ON attributes.term_id = summarize.term_id
			",
			$filtered_attribute,
			$join_type,
			$where_clause
		)
	);

	// phpcs:enable
	$results = array_map( 'absint', wp_list_pluck( $counts, 'term_count', 'term_count_id' ) );

	set_transient( $transient_key, $results, 24 * HOUR_IN_SECONDS );

	return $results;
}