WC_Product_Variable_Data_Store_CPT::read_attributes
Read attributes from post meta.
Method of the class: WC_Product_Variable_Data_Store_CPT{}
Hooks from the method
Returns
null. Nothing (null).
Usage
// protected - for code of main (parent) or child class $result = $this->read_attributes( $product );
- $product(WC_Product) (required) (passed by reference — &)
- Product object.
WC_Product_Variable_Data_Store_CPT::read_attributes() WC Product Variable Data Store CPT::read attributes code WC 10.7.0
protected function read_attributes( &$product ) {
$product_id = $product->get_id();
$meta_attributes = get_post_meta( $product_id, '_product_attributes', true );
if ( ! empty( $meta_attributes ) && is_array( $meta_attributes ) ) {
$attributes = array();
$force_update = false;
foreach ( $meta_attributes as $meta_attribute_key => $meta_attribute_value ) {
$meta_value = array_merge(
array(
'name' => '',
'value' => '',
'position' => 0,
'is_visible' => 0,
'is_variation' => 0,
'is_taxonomy' => 0,
),
(array) $meta_attribute_value
);
// Maintain data integrity: WordPress 4.9 changed sanitization functions, and we update the values here so variations function correctly.
// As per 2026, we are refactoring the updates into product-level: BC-focused (not all-in on-spot migration), optimized for performance.
// Use-case: `_product_attributes` has data populated on WordPress pre-4.8 and containing symbols affected by the breaking changes.
if ( $meta_value['is_variation'] && strstr( $meta_value['name'], '/' ) && sanitize_title( $meta_value['name'] ) !== $meta_attribute_key ) {
global $wpdb;
$child_ids = $product->get_children();
if ( ! empty( $child_ids ) ) {
$products_to_migrate = implode( ', ', $child_ids );
$old_slug = 'attribute_' . $meta_attribute_key;
$old_meta_rows = $wpdb->get_results(
$wpdb->prepare(
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s AND post_id IN ( $products_to_migrate )",
$old_slug
)
);
if ( $old_meta_rows ) {
$new_slug = 'attribute_' . sanitize_title( $meta_value['name'] );
foreach ( $old_meta_rows as $old_meta_row ) {
update_post_meta( $old_meta_row->post_id, $new_slug, $old_meta_row->meta_value );
}
}
}
$force_update = true;
}
// Check if is a taxonomy attribute.
if ( ! empty( $meta_value['is_taxonomy'] ) ) {
if ( ! taxonomy_exists( $meta_value['name'] ) ) {
continue;
}
$id = wc_attribute_taxonomy_id_by_name( $meta_value['name'] );
$options = wc_get_object_terms( $product_id, $meta_value['name'], 'term_id' );
} else {
$id = 0;
$options = wc_get_text_attributes( $meta_value['value'] );
}
$attribute = new WC_Product_Attribute();
$attribute->set_id( $id );
$attribute->set_name( $meta_value['name'] );
$attribute->set_options( $options );
$attribute->set_position( $meta_value['position'] );
$attribute->set_visible( $meta_value['is_visible'] );
$attribute->set_variation( $meta_value['is_variation'] );
/**
* Filter product attribute after initialization.
*
* @since 10.6.0
*
* @param WC_Product_Attribute $attribute The attribute object.
* @param array $meta_value The meta value.
* @param WC_Product $product The product object.
*/
$attributes[] = apply_filters( 'woocommerce_product_read_attribute', $attribute, $meta_value, $product );
}
$product->set_attributes( $attributes );
if ( $force_update ) {
$this->update_attributes( $product, true );
}
}
}