Merge pull request #23067 from woocommerce/pr/23043

Allow matching of "any" attributes in find_matching_product_variation…
This commit is contained in:
Claudio Sanches 2019-07-12 12:40:53 -03:00 committed by GitHub
commit 60c18ce544
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 153 additions and 16 deletions

View File

@ -3929,8 +3929,6 @@ img.help_tip {
top: 20px;
}
woocommerce-help-tip
.select2-container {
vertical-align: top;
margin-bottom: 3px;

View File

@ -1068,14 +1068,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
if ( ! $attribute->get_variation() ) {
continue;
}
$attribute_field_name = 'attribute_' . sanitize_title( $attribute->get_name() );
if ( ! isset( $match_attributes[ $attribute_field_name ] ) ) {
return 0;
}
$meta_attribute_names[] = $attribute_field_name;
$meta_attribute_names[] = 'attribute_' . sanitize_title( $attribute->get_name() );
}
// Get the attributes of the variations.
@ -1117,10 +1110,17 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
foreach ( $sorted_meta as $variation_id => $variation ) {
$match = true;
foreach ( $match_attributes as $attribute_key => $attribute_value ) {
if ( array_key_exists( $attribute_key, $variation ) ) {
if ( $variation[ $attribute_key ] !== $attribute_value && ( '0' === $variation[ $attribute_key ] || $variation[ $attribute_key ] ) ) {
$match = false;
// 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 = empty( $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.
}
}
}
@ -1137,6 +1137,8 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
*/
return ( array_map( 'sanitize_title', $match_attributes ) === $match_attributes ) ? 0 : $this->find_matching_product_variation( $product, array_map( 'sanitize_title', $match_attributes ) );
}
return 0;
}
/**

View File

@ -116,9 +116,20 @@ class WC_Helper_Product {
)
);
$attribute_data = self::create_attribute( 'size', array( 'small', 'large' ) ); // Create all attribute related things.
$attributes = array();
$attribute = new WC_Product_Attribute();
$attribute_data = self::create_attribute( 'size', array( 'small', 'large' ) );
$attribute->set_id( $attribute_data['attribute_id'] );
$attribute->set_name( $attribute_data['attribute_taxonomy'] );
$attribute->set_options( $attribute_data['term_ids'] );
$attribute->set_position( 1 );
$attribute->set_visible( true );
$attribute->set_variation( true );
$attributes[] = $attribute;
$attribute = new WC_Product_Attribute();
$attribute_data = self::create_attribute( 'colour', array( 'red', 'blue' ) );
$attribute->set_id( $attribute_data['attribute_id'] );
$attribute->set_name( $attribute_data['attribute_taxonomy'] );
$attribute->set_options( $attribute_data['term_ids'] );

View File

@ -229,7 +229,10 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$this->assertEquals( $expected_prices, $product->get_variation_prices() );
$expected_attributes = array( 'pa_size' => array( 'small', 'large' ) );
$expected_attributes = array(
'pa_size' => array( 'small', 'large' ),
'pa_colour' => array( 'blue', 'red' ),
);
$this->assertEquals( $expected_attributes, $product->get_variation_attributes() );
}
@ -910,4 +913,127 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$count = $data_store->create_all_product_variations( wc_get_product( $product_id ), 10 );
$this->assertEquals( 7, $count );
}
/**
* Test find_matching_product_variation.
*
* @return void
*/
public function test_find_matching_product_variation() {
$product = WC_Helper_Product::create_variation_product();
$data_store = WC_Data_Store::load( 'product' );
$children = $product->get_children();
$match = $data_store->find_matching_product_variation( $product, array() );
$this->assertEquals( 0, $match );
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => 'small',
)
);
$this->assertEquals( $children[0], $match );
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => 'large',
)
);
$this->assertEquals( $children[1], $match );
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => 'small',
'attribute_pa_colour' => '',
)
);
$this->assertEquals( $children[0], $match );
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => 'large',
'attribute_pa_colour' => '',
)
);
$this->assertEquals( $children[1], $match );
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => 'small',
'attribute_pa_colour' => 'red',
)
);
$this->assertEquals( $children[0], $match );
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => 'large',
'attribute_pa_colour' => 'blue',
)
);
$this->assertEquals( $children[1], $match );
// Test against non matching colour, should still return first attribute.
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => 'small',
'attribute_pa_colour' => 'pink',
)
);
$this->assertEquals( $children[0], $match );
// Test against non matching colour, should still return first attribute.
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => 'large',
'attribute_pa_colour' => 'pink',
)
);
$this->assertEquals( $children[1], $match );
// Test non expected matches.
// If second attribute in variation is any and you omit the first attribute it should not match anything.
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_colour' => 'blue',
)
);
$this->assertEquals( 0, $match );
// If second attribute in variation is any and you pass a blank in the first attribute it should not match anything.
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => '',
'attribute_pa_colour' => 'red',
)
);
$this->assertEquals( 0, $match );
// Passing blanks as both attributes should not match anything.
$match = $data_store->find_matching_product_variation(
$product,
array(
'attribute_pa_size' => '',
'attribute_pa_colour' => '',
)
);
$this->assertEquals( 0, $match );
// Passing an empty array should not match anything.
$match = $data_store->find_matching_product_variation(
$product,
array()
);
$this->assertEquals( 0, $match );
}
}