/**
  * Update attributes which are a mix of terms and meta data.
  *
  * @param WC_Product
  * @since 2.7.0
  */
 protected function update_attributes(&$product)
 {
     $attributes = $product->get_attributes();
     $meta_values = array();
     if ($attributes) {
         foreach ($attributes as $attribute_key => $attribute) {
             $value = '';
             if (is_null($attribute)) {
                 if (taxonomy_exists($attribute_key)) {
                     // Handle attributes that have been unset.
                     wp_set_object_terms($product->get_id(), array(), $attribute_key);
                 }
                 continue;
             } elseif ($attribute->is_taxonomy()) {
                 wp_set_object_terms($product->get_id(), wp_list_pluck($attribute->get_terms(), 'term_id'), $attribute->get_name());
             } else {
                 $value = wc_implode_text_attributes($attribute->get_options());
             }
             // Store in format WC uses in meta.
             $meta_values[$attribute_key] = array('name' => $attribute->get_name(), 'value' => $value, 'position' => $attribute->get_position(), 'is_visible' => $attribute->get_visible() ? 1 : 0, 'is_variation' => $attribute->get_variation() ? 1 : 0, 'is_taxonomy' => $attribute->is_taxonomy() ? 1 : 0);
         }
     }
     update_post_meta($product->get_id(), '_product_attributes', $meta_values);
 }
							<?php 
    do_action('woocommerce_product_option_terms', $attribute_taxonomy, $i);
    ?>

						<?php 
} else {
    ?>

							<textarea name="attribute_values[<?php 
    echo $i;
    ?>
]" cols="5" rows="5" placeholder="<?php 
    echo esc_attr(sprintf(__('Enter some text, or some attributes by "%s" separating values.', 'woocommerce'), WC_DELIMITER));
    ?>
"><?php 
    echo esc_textarea(wc_implode_text_attributes($attribute->get_options()));
    ?>
</textarea>

						<?php 
}
?>
					</td>
				</tr>
				<tr>
					<td>
						<label><input type="checkbox" class="checkbox" <?php 
checked($attribute->get_visible(), true);
?>
 name="attribute_visibility[<?php 
echo $i;
 /**
  * Returns a single product attribute as a string.
  * @param  string $attribute to get.
  * @return string
  */
 public function get_attribute($attribute)
 {
     $attributes = $this->get_attributes();
     $attribute = sanitize_title($attribute);
     if (isset($attributes[$attribute])) {
         $attribute_object = $attributes[$attribute];
     } elseif (isset($attributes['pa_' . $attribute])) {
         $attribute_object = $attributes['pa_' . $attribute];
     } else {
         return '';
     }
     return $attribute_object->is_taxonomy() ? implode(', ', wc_get_object_terms($this->get_id(), $attribute_object->get_name(), 'name')) : wc_implode_text_attributes($attribute_object->get_options());
 }
 /**
  * offsetGet
  * @param string $offset
  * @return mixed
  */
 public function offsetGet($offset)
 {
     switch ($offset) {
         case 'is_variation':
             return $this->get_variation() ? 1 : 0;
             break;
         case 'is_visible':
             return $this->get_visible() ? 1 : 0;
             break;
         case 'is_taxonomy':
             return $this->is_taxonomy() ? 1 : 0;
             break;
         case 'value':
             return $this->is_taxonomy() ? '' : wc_implode_text_attributes($this->get_options());
             break;
         default:
             if (is_callable(array($this, "get_{$offset}"))) {
                 return $this->{"get_{$offset}"}();
             }
             break;
     }
     return '';
 }