Creating custom Woocommerce attribute taxonomies from a plugin

For 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))

Leave a Comment