WC_Structured_Data::get_selected_variationprivateWC 1.0

Resolve the variation targeted by the current request, if any.

A variation is only returned when every variation attribute of the product is present in the request (e.g. ?attribute_pa_size=large&attribute_color=red) and they unambiguously identify a single, purchasable variation. Partial or missing selections return null so the parent product's AggregateOffer is used instead.

Method of the class: WC_Structured_Data{}

No Hooks.

Returns

WC_Product_Variation|null. The selected variation, or null when not uniquely identified.

Usage

// private - for code of main (parent) class only
$result = $this->get_selected_variation( $product );
$product(WC_Product) (required)
Variable product.

WC_Structured_Data::get_selected_variation() code WC 11.0.1

private function get_selected_variation( $product ) {
	if ( ! $product instanceof WC_Product_Variable ) {
		return null;
	}

	$variation_attributes = $product->get_variation_attributes();

	if ( empty( $variation_attributes ) ) {
		return null;
	}

	$match_attributes = array();

	foreach ( $variation_attributes as $attribute_name => $options ) {
		$key = wc_variation_attribute_name( $attribute_name );

		// Require every variation attribute to be specified so a single variation is identified.
		if ( ! isset( $_GET[ $key ] ) || '' === $_GET[ $key ] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return null;
		}

		$match_attributes[ $key ] = wc_clean( wp_unslash( $_GET[ $key ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
	}

	$data_store = WC_Data_Store::load( 'product' );
	// @phpstan-ignore-next-line method.notFound (Called via __call() on the underlying product data store instance.)
	$variation_id = $data_store->find_matching_product_variation( $product, $match_attributes );

	if ( ! $variation_id ) {
		return null;
	}

	// `find_matching_product_variation()` returns the first match by menu order, so a fully-specified
	// selection can still be ambiguous when an overlapping "Any" variation also matches it. Only treat
	// the selection as a single Offer when exactly one variation matches; otherwise the price is
	// ambiguous and we keep the parent's AggregateOffer.
	if ( 1 !== $this->count_matching_variations( $product, $match_attributes ) ) {
		return null;
	}

	$variation = wc_get_product( $variation_id );

	if ( ! $variation instanceof WC_Product_Variation || '' === $variation->get_price() ) {
		return null;
	}

	return $variation;
}