diff --git a/includes/abstracts/abstract-wc-product.php b/includes/abstracts/abstract-wc-product.php index 0f0738ac098..b33d9605815 100644 --- a/includes/abstracts/abstract-wc-product.php +++ b/includes/abstracts/abstract-wc-product.php @@ -1066,7 +1066,8 @@ class WC_Product extends WC_Abstract_Legacy_Product { * @param array $default_attributes List of default attributes. */ public function set_default_attributes( $default_attributes ) { - $this->set_prop( 'default_attributes', array_filter( (array) $default_attributes ) ); + $this->set_prop( 'default_attributes', + array_filter( (array) $default_attributes, 'wc_array_filter_default_attributes' ) ); } /** diff --git a/includes/wc-attribute-functions.php b/includes/wc-attribute-functions.php index a79d27697cd..f739d73929f 100644 --- a/includes/wc-attribute-functions.php +++ b/includes/wc-attribute-functions.php @@ -332,3 +332,15 @@ function wc_is_attribute_in_product_name( $attribute, $name ) { $is_in_name = stristr( $name, ' ' . $attribute . ',' ) || 0 === stripos( strrev( $name ), strrev( ' ' . $attribute ) ); return apply_filters( 'woocommerce_is_attribute_in_product_name', $is_in_name, $attribute, $name ); } + +/** + * Callback for array filter to get default attributes. Will allow for '0' string values, but regard all other + * class PHP FALSE equivalents normally. + * + * @since 3.1.0 + * @param mixed $attribute Attribute being considered for exclusion from parent array. + * @return bool + */ +function wc_array_filter_default_attributes( $attribute ) { + return ( ! empty( $attribute ) || $attribute === '0' ); +} diff --git a/tests/unit-tests/product/data-store.php b/tests/unit-tests/product/data-store.php index 1de43388f29..054387a1cb2 100644 --- a/tests/unit-tests/product/data-store.php +++ b/tests/unit-tests/product/data-store.php @@ -316,7 +316,7 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case { $product->delete(); } - function test_varation_save_attributes() { + function test_variation_save_attributes() { // Create a variable product with a color attribute. $product = new WC_Product_Variable; @@ -350,6 +350,44 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case { $this->assertEquals( 'green', $_attribute['color'] ); } + public function test_save_default_attributes() { + + // Create a variable product with sold individually. + $product = new WC_Product_Variable; + $product->save(); + $product_id = $product->get_id(); + + // Save with a set of FALSE equivalents and some values we expect to come through as true. We should see + // string types with a value of '0' making it through filtration. + $test_object = new stdClass(); + $test_object->property = '12345'; + $product->set_default_attributes( array( + 'sample-attribute-false-0' => 0, + 'sample-attribute-false-1' => false, + 'sample-attribute-false-2' => '', + 'sample-attribute-false-3' => null, + 'sample-attribute-true-0' => '0', + 'sample-attribute-true-1' => 1, + 'sample-attribute-true-2' => 'true', + 'sample-attribute-true-3' => 'false', + 'sample-attribute-true-4' => array( 'exists' => 'false' ), + 'sample-attribute-false-4' => $test_object, + )); + $product->save(); + + // Revive the product from the database and analyze results + $product = wc_get_product( $product_id ); + $default_attributes = $product->get_default_attributes(); + $this->assertEquals( $default_attributes, array( + 'sample-attribute-true-0' => '0', + 'sample-attribute-true-1' => 1, + 'sample-attribute-true-2' => 'true', + 'sample-attribute-true-3' => 'false', + 'sample-attribute-true-4' => array( 'exists' => 'false' ), + 'sample-attribute-false-4' => $test_object, + )); + } + function test_variable_child_has_dimensions() { $product = new WC_Product_Variable; $product->save();