web-dev-qa-db-fra.com

Création de taxonomies d'attributs Woocommerce personnalisées à partir d'un plugin

J'ai créé un plugin pour importer des produits vers Wordpress avec Woocommerce. Cela fonctionne très bien, à l'exception des attributs du produit. Je ne parviens pas à les importer correctement.

Le problème est qu'avec les produits, j'ajoute des taxonomies personnalisées qui ne sont pas définies dans le tableau de bord. Étonnamment, je ne trouve pas de méthode pour cela. J'ai essayé wp_insert_term() avec register_taxonomy(), mais cela n'ajoute rien à la table wp_woocommerce_attribute_taxonomies de la base de données et je ne les trouve pas non plus dans les attributs du produit, ni dans la page des attributs du produit dans le tableau de bord. Je ne les ai trouvés que dans la table wp_terms de la base de données et, d'après ce que j'ai appris, ce n'est pas à quoi les attributs du produit appartiennent dans Woocommerce.

update_post_meta() également ne semble pas fonctionner (il peut ajouter des attributs en tant que méta, mais j'en ai besoin en tant qu'attributs de produit de Woocommerce).

Je dois créer des attributs s'ils n'existent pas avant d'importer les produits. Y at-il une fonction pour faire cela que j'ai négligée?

Je ne sais pas si je devrais publier ce que j'ai à ce jour, mais voici le code lié à la question:

// 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
        )
    );
}
3
Dmitriy Demir

Pour une raison quelconque, Woocommerce ne semble pas vouloir que vous le fassiez. Vous ne savez pas trop pourquoi, car le fait de le faire manuellement pose un problème d'évolutivité dans un certain nombre de cas (sans oublier de mentionner que si vous avez des attributs avec beaucoup de valeurs possibles, l'interface qu'ils fournissent charge vraiment lentement). Après avoir creusé un peu, voici les fonctions privées utilisées par les pages d’administrateur, modifiées pour les appels systémiques.

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;
}

Appelé comme suit:

$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); }

Les champs associés à l'attribut sont le nom (slug standard wp), le libellé (version lisible par l'homme du nom de l'attribut), le type (vous avez le choix entre 'sélectionner' et 'texte', mais si vous créez systématiquement, vous veux probablement du texte que j'ai modifié la fonction pour lui appliquer la valeur par défaut), public (appelé "Enable Archives" dans l'interface, j'ai rendu la fonction par défaut à l'interface par défaut), et orderby (les options sont 'menu_order' (désigné par 'Personnalisé ordre 'dans l'interface),' nom '(auto-explicatif),' nom_num '(nom numérique) et' id '(terme id))

7
Ardidaj