I've made a plugin to import products to Wordpress with Woocommerce. It works fine except the product attributes - I can't find a way to import them properly.
The issue is that with products I add custom taxonomies which are not defined in the dashboard. Surprisingly I can't find a method for this. I tried wp_insert_term()
with register_taxonomy()
, but these don't add anything to the wp_woocommerce_attribute_taxonomies
table in the database and I don't find them in the product's attributes neither on the product attributes page in the dashboard. I only found them in wp_terms
table in the database and from what I learned it's not where product attributes belong in Woocommerce.
update_post_meta()
also doesn't seem to work (it can add attributes as meta, but I need them as Woocommerce's product attributes).
I need to create attributes if they don't exist before I import the products. Is there a function to do this that I overlooked?
Not sure if I should post what I have so far, but here is the code related to the issue:
// This is an example of what I get from my AJAX input
$product_attributes = array(
"attr_id_01" => array(
"name" => "Material",
"value" => "Metal",
"is_visible" => 1,
"is_taxonomy" => 1
),
"attr_id_02" => array(
"name" => "Type",
"value" => "Has a handle",
"is_visible" => 1,
"is_taxonomy" => 1
)
);
foreach ($product_attributes_copy as $key => $value) {
// sanitize_title filter is provided by CyrToLat plugin,
// it basically makes the string url-friendly,
// it's used because names and values could contain Cyrillic, uppercase and spaces
$filtered_name = apply_filters('sanitize_title', $value['name']);
$filtered_value = apply_filters('sanitize_title', $value['value']);
$taxonomy = 'pa_' . $filtered_name;
$parent_term = term_exists( $filtered_value, $taxonomy );
$parent_term_id = $parent_term['term_id'];
if ( ! taxonomy_exists($taxonomy) ) {
register_taxonomy($taxonomy, 'product', array('label' => $value['name']) );
}
// No errors from the following
$insert_result = wp_insert_term(
$filtered_value,
$taxonomy,
array(
'description'=> '',
'slug' => $filtered_value,
'parent'=> $parent_term_id
)
);
}
I've made a plugin to import products to Wordpress with Woocommerce. It works fine except the product attributes - I can't find a way to import them properly.
The issue is that with products I add custom taxonomies which are not defined in the dashboard. Surprisingly I can't find a method for this. I tried wp_insert_term()
with register_taxonomy()
, but these don't add anything to the wp_woocommerce_attribute_taxonomies
table in the database and I don't find them in the product's attributes neither on the product attributes page in the dashboard. I only found them in wp_terms
table in the database and from what I learned it's not where product attributes belong in Woocommerce.
update_post_meta()
also doesn't seem to work (it can add attributes as meta, but I need them as Woocommerce's product attributes).
I need to create attributes if they don't exist before I import the products. Is there a function to do this that I overlooked?
Not sure if I should post what I have so far, but here is the code related to the issue:
// This is an example of what I get from my AJAX input
$product_attributes = array(
"attr_id_01" => array(
"name" => "Material",
"value" => "Metal",
"is_visible" => 1,
"is_taxonomy" => 1
),
"attr_id_02" => array(
"name" => "Type",
"value" => "Has a handle",
"is_visible" => 1,
"is_taxonomy" => 1
)
);
foreach ($product_attributes_copy as $key => $value) {
// sanitize_title filter is provided by CyrToLat plugin,
// it basically makes the string url-friendly,
// it's used because names and values could contain Cyrillic, uppercase and spaces
$filtered_name = apply_filters('sanitize_title', $value['name']);
$filtered_value = apply_filters('sanitize_title', $value['value']);
$taxonomy = 'pa_' . $filtered_name;
$parent_term = term_exists( $filtered_value, $taxonomy );
$parent_term_id = $parent_term['term_id'];
if ( ! taxonomy_exists($taxonomy) ) {
register_taxonomy($taxonomy, 'product', array('label' => $value['name']) );
}
// No errors from the following
$insert_result = wp_insert_term(
$filtered_value,
$taxonomy,
array(
'description'=> '',
'slug' => $filtered_value,
'parent'=> $parent_term_id
)
);
}
Share
Improve this question
edited Oct 28, 2016 at 20:32
Dmitry Gamolin
asked Oct 28, 2016 at 20:25
Dmitry GamolinDmitry Gamolin
4831 gold badge6 silver badges20 bronze badges
1 Answer
Reset to default 10For some reason, Woocommerce doesn't seem to want you to do this. Not sure why, because requiring it to be done manually is a problem for scalability in a number of cases (not to mention, if you have attributes with a lot of possible values, the interface they provide loads really slowly). After digging a bit, here's the private functions that the admin pages use, modified for systemic call.
function process_add_attribute($attribute)
{
global $wpdb;
// check_admin_referer( 'woocommerce-add-new_attribute' );
if (empty($attribute['attribute_type'])) { $attribute['attribute_type'] = 'text';}
if (empty($attribute['attribute_orderby'])) { $attribute['attribute_orderby'] = 'menu_order';}
if (empty($attribute['attribute_public'])) { $attribute['attribute_public'] = 0;}
if ( empty( $attribute['attribute_name'] ) || empty( $attribute['attribute_label'] ) ) {
return new WP_Error( 'error', __( 'Please, provide an attribute name and slug.', 'woocommerce' ) );
} elseif ( ( $valid_attribute_name = valid_attribute_name( $attribute['attribute_name'] ) ) && is_wp_error( $valid_attribute_name ) ) {
return $valid_attribute_name;
} elseif ( taxonomy_exists( wc_attribute_taxonomy_name( $attribute['attribute_name'] ) ) ) {
return new WP_Error( 'error', sprintf( __( 'Slug "%s" is already in use. Change it, please.', 'woocommerce' ), sanitize_title( $attribute['attribute_name'] ) ) );
}
$wpdb->insert( $wpdb->prefix . 'woocommerce_attribute_taxonomies', $attribute );
do_action( 'woocommerce_attribute_added', $wpdb->insert_id, $attribute );
flush_rewrite_rules();
delete_transient( 'wc_attribute_taxonomies' );
return true;
}
function valid_attribute_name( $attribute_name ) {
if ( strlen( $attribute_name ) >= 28 ) {
return new WP_Error( 'error', sprintf( __( 'Slug "%s" is too long (28 characters max). Shorten it, please.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
} elseif ( wc_check_if_attribute_name_is_reserved( $attribute_name ) ) {
return new WP_Error( 'error', sprintf( __( 'Slug "%s" is not allowed because it is a reserved term. Change it, please.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
}
return true;
}
Called as follows:
$insert = proccess_add_attribute(array('attribute_name' => 'my-new-slug', 'attribute_label' => 'my-new-attribute', 'attribute_type' => 'text', 'attribute_orderby' => 'menu_order', 'attribute_public' => false));
if (is_wp_error($insert)) { do_something_for_error($insert); }
The fields associated with the attribute are the name (standard wp slug), label (human readable version of the attribute name), type (you have a choice between 'select' and 'text', but if you're creating systemically, you probably want text I modified the function to default to it), public (labeled as "Enable Archives" in the interface, I made the function default to the interface default), and orderby (choices are 'menu_order' (refered to as 'Custom ordering' in the interface), 'name' (self explanitory), 'name_num' (numeric name), and 'id' (term id))