Creare tassonomie personalizzate per attributi Woocommerce da un plugin

28 ott 2016, 23:25:33
Visualizzazioni: 17.5K
Voti: 4

Ho creato un plugin per importare prodotti in Wordpress con Woocommerce. Funziona bene tranne che per gli attributi dei prodotti - non riesco a trovare un modo per importarli correttamente.

Il problema è che con i prodotti aggiungo tassonomie personalizzate che non sono definite nella dashboard. Sorprendentemente non trovo un metodo per farlo. Ho provato wp_insert_term() con register_taxonomy(), ma questi non aggiungono nulla alla tabella wp_woocommerce_attribute_taxonomies nel database e non li trovo né negli attributi del prodotto né nella pagina degli attributi prodotti nella dashboard. Li ho trovati solo nella tabella wp_terms del database e da quello che ho capito non è dove dovrebbero stare gli attributi dei prodotti in Woocommerce.

update_post_meta() sembra non funzionare neanche (può aggiungere attributi come meta, ma a me servono come attributi prodotto di Woocommerce).

Devo creare gli attributi se non esistono prima di importare i prodotti. C'è una funzione per farlo che ho trascurato?

Non sono sicuro se dovrei postare quello che ho finora, ma ecco il codice relativo al problema:

// Questo è un esempio di quello che ricevo dal mio input AJAX
$product_attributes = array(
    "attr_id_01" => array(
        "name" => "Materiale",
        "value" => "Metallo",
        "is_visible" => 1,
        "is_taxonomy" => 1
    ),
    "attr_id_02" => array(
        "name" => "Tipo",
        "value" => "Ha una maniglia",
        "is_visible" => 1,
        "is_taxonomy" => 1
    )
);
foreach ($product_attributes_copy as $key => $value) {
    // sanitize_title è un filtro fornito dal plugin CyrToLat,
    // rende fondamentalmente la stringa url-friendly,
    // viene usato perché nomi e valori potrebbero contenere cirillico, maiuscole e spazi
    $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']) );
    }

    // Nessun errore dal seguente
    $insert_result = wp_insert_term(
        $filtered_value,
        $taxonomy,
        array(
            'description'=> '',
            'slug' => $filtered_value,
            'parent'=> $parent_term_id
        )
    );
}
0
Tutte le risposte alla domanda 1
1
10

Per qualche motivo, Woocommerce sembra non voler permettere di fare questa operazione. Non sono sicuro del perché, dato che richiederne l'esecuzione manuale rappresenta un problema di scalabilità in diversi casi (per non parlare del fatto che, se si hanno attributi con molti valori possibili, l'interfaccia fornita diventa estremamente lenta). Dopo aver scavato un po', ecco le funzioni private utilizzate dalle pagine di amministrazione, modificate per essere chiamate sistematicamente.

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', __( 'Per favore, fornisci un nome e uno slug per l\'attributo.', '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( __( 'Lo slug "%s" è già in uso. Modificalo, per favore.', '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( __( 'Lo slug "%s" è troppo lungo (massimo 28 caratteri). Accorcialo, per favore.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
    } elseif ( wc_check_if_attribute_name_is_reserved( $attribute_name ) ) {
            return new WP_Error( 'error', sprintf( __( 'Lo slug "%s" non è permesso perché è un termine riservato. Modificalo, per favore.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
    }

    return true;
}

Da chiamare come segue:

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

I campi associati all'attributo sono il nome (slug standard di WordPress), label (versione leggibile dell'utente del nome dell'attributo), type (si può scegliere tra 'select' e 'text', ma se si crea sistematicamente, probabilmente si vorrà usare text - ho modificato la funzione per impostarlo come predefinito), public (etichettato come "Abilita archivi" nell'interfaccia, ho impostato la funzione sul valore predefinito dell'interfaccia) e orderby (le opzioni sono 'menu_order' (indicato come 'Ordinamento personalizzato' nell'interfaccia), 'name' (autoesplicativo), 'name_num' (nome numerico) e 'id' (ID del termine)).

18 nov 2016 22:44:49
Commenti

L'ho risolto in modo diverso, ma non ho pubblicato la soluzione qui perché non è abbastanza generica e nemmeno bella come avrei voluto (ma sembra che non ci sia una soluzione elegante per questo con Woocommerce...). Penso che il tuo codice dovrebbe funzionare anche, quindi lo segnerò come risposta. E grazie per lo sforzo con la spiegazione!

Dmitry Gamolin Dmitry Gamolin
19 nov 2016 14:07:22