WC_Product_Data_Store_CPT::find_matching_product_variation()
Find a matching (enabled) variation within a variable product.
Method of the class: WC_Product_Data_Store_CPT{}
No Hooks.
Return
Int
. Matching variation ID or 0.
Usage
$WC_Product_Data_Store_CPT = new WC_Product_Data_Store_CPT(); $WC_Product_Data_Store_CPT->find_matching_product_variation( $product, $match_attributes );
- $product(WC_Product) (required)
- Variable product.
- $match_attributes(array)
- Array of attributes we want to try to match.
Default: array()
Changelog
Since 3.0.0 | Introduced. |
WC_Product_Data_Store_CPT::find_matching_product_variation() WC Product Data Store CPT::find matching product variation code WC 9.3.3
public function find_matching_product_variation( $product, $match_attributes = array() ) { if ( 'variation' === $product->get_type() ) { // Can't get a variation of a variation. return 0; } global $wpdb; $meta_attribute_names = array(); // Get attributes to match in meta. foreach ( $product->get_attributes() as $attribute ) { if ( ! $attribute->get_variation() ) { continue; } $meta_attribute_names[] = 'attribute_' . sanitize_title( $attribute->get_name() ); } // Get the attributes of the variations. $query = $wpdb->prepare( " SELECT postmeta.post_id, postmeta.meta_key, postmeta.meta_value, posts.menu_order FROM {$wpdb->postmeta} as postmeta LEFT JOIN {$wpdb->posts} as posts ON postmeta.post_id=posts.ID WHERE postmeta.post_id IN ( SELECT ID FROM {$wpdb->posts} WHERE {$wpdb->posts}.post_parent = %d AND {$wpdb->posts}.post_status = 'publish' AND {$wpdb->posts}.post_type = 'product_variation' ) ", $product->get_id() ); $query .= " AND postmeta.meta_key IN ( '" . implode( "','", array_map( 'esc_sql', $meta_attribute_names ) ) . "' )"; $query .= ' ORDER BY posts.menu_order ASC, postmeta.post_id ASC;'; $attributes = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared if ( ! $attributes ) { return 0; } $sorted_meta = array(); foreach ( $attributes as $m ) { $sorted_meta[ $m->post_id ][ $m->meta_key ] = $m->meta_value; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key } /** * Check each variation to find the one that matches the $match_attributes. * * Note: Not all meta fields will be set which is why we check existence. */ foreach ( $sorted_meta as $variation_id => $variation ) { $match = true; // Loop over the variation meta keys and values i.e. what is saved to the products. Note: $attribute_value is empty when 'any' is in use. foreach ( $variation as $attribute_key => $attribute_value ) { $match_any_value = '' === $attribute_value; if ( ! $match_any_value && ! array_key_exists( $attribute_key, $match_attributes ) ) { $match = false; // Requires a selection but no value was provide. } if ( array_key_exists( $attribute_key, $match_attributes ) ) { // Value to match was provided. if ( ! $match_any_value && $match_attributes[ $attribute_key ] !== $attribute_value ) { $match = false; // Provided value does not match variation. } } } if ( true === $match ) { return $variation_id; } } if ( version_compare( get_post_meta( $product->get_id(), '_product_version', true ), '2.4.0', '<' ) ) { /** * Pre 2.4 handling where 'slugs' were saved instead of the full text attribute. * Fallback is here because there are cases where data will be 'synced' but the product version will remain the same. */ return ( array_map( 'sanitize_title', $match_attributes ) === $match_attributes ) ? 0 : $this->find_matching_product_variation( $product, array_map( 'sanitize_title', $match_attributes ) ); } return 0; }