WOOT - WooCommerce Active Products Tables

Personnaliser la fenêtre des variations d’un tableau de produits WooCommerce

La fenêtre des variations d’un tableau de produits WooCommerce, celle qui s’ouvre lorsqu’un visiteur clique sur select [5] à côté d’un produit variable, est elle-même un petit tableau de produits. Pour personnaliser la fenêtre des variations, vous modifiez ce tableau : ses colonnes, le nombre de lignes par page, l’ordre de tri, les champs supplémentaires et l’apparence. Une partie relève d’un réglage, le reste demande quelques lignes de code. Chaque tâche est présentée ci-dessous, avec la raison pour laquelle elle fonctionne ainsi.

Comment fonctionne la fenêtre des variations d’un tableau de produits WooCommerce

Deux boutons ouvrent la fenêtre. Dans la colonne Panier (Cart), un produit variable reçoit select [N] à la place d’un bouton Ajouter au panier (Add to cart), et la colonne Variations affiche Var.[N], où N est le nombre de variations. Les deux chargent le tableau [woot_variations] pour ce produit.

  • La fenêtre n’utilise pas les colonnes du tableau depuis lequel elle a été ouverte. Ses colonnes proviennent de WOOT → Paramètres (Settings) → Colonnes des variations (Variations columns) ; seul le thème visuel est repris du tableau parent.
  • Toutes les variations du produit sont chargées d’un coup, puis paginées et triées dans le navigateur : 10 lignes par page, pagination en haut, lignes triées par ordre alphabétique selon la cellule Titre (Title). Le titre d’une variation est le nom du produit suivi de ses valeurs d’attributs, ce qui explique que les tailles soient classées L, M, S, XL.
  • La fenêtre est toujours un tableau. Sa disposition ne peut pas être remplacée par un modèle, mais chaque colonne qu’elle contient peut être modifiée ou ajoutée.

Les modifications par code passent par un seul filtre, woot_vurgc_shortcode_data. Il s’exécute pour les tableaux de variations, de produits suggérés, de ventes croisées, de produits groupés et de produits similaires juste avant l’affichage du tableau, et reçoit tous ses arguments : filter_provider vaut woot_variations pour les variations, et filter_data['product_id'] contient le produit. D’anciens extraits utilisaient woot_review_shortcode_args, qui filtre chaque tableau [woot] du site ; utilisez plutôt le hook dédié. Tous les extraits ci-dessous se placent dans le fichier functions.php d’un thème enfant ou dans un plugin d’extraits de code.

Personnaliser les colonnes de la fenêtre des variations

Ouvrez WOOT → Paramètres (Settings), trouvez Colonnes des variations (Variations columns) et sélectionnez les champs souhaités ; maintenez le clic sur un champ sélectionné pour le glisser vers une autre position. La liste s’applique à chaque fenêtre de variations et à chaque shortcode [woot_variations] qui n’a pas ses propres colonnes. Le bouton Toutes les clés de colonnes possibles (All possible columns keys), sous le tableau des réglages, liste la clé de chaque champ.

Un tableau de variations placé sur une page peut avoir ses propres colonnes : [woot_variations id=49 columns='thumbnail,pa_size,pa_color,price,add_to_cart'], où id est l’ID du produit. Sur une page de produit unique, l’ID peut être omis et le produit courant est utilisé ; voir comment insérer des shortcodes dans la page de produit unique.

Deux précisions font gagner du temps. Les colonnes d’attributs comme pa_size affichent la valeur de chaque variation, et le titre reçoit lui aussi les valeurs d’attributs, mais uniquement pour les attributs globaux créés sous Produits → Attributs (Products → Attributes). Les valeurs des attributs personnalisés saisis directement dans un produit n’apparaissent ni dans le titre ni sous forme de colonne. Ensuite, l’en-tête par défaut d’une colonne d’attribut est le nom de la taxonomie WooCommerce, par exemple Product Size ; renommez-le avec le Vocabulaire.

Lignes par page et pagination

Sur une page, utilisez l’attribut per_page : [woot_variations id=49 per_page=4], ou per_page=-1 pour afficher toutes les variations sans pagination. Pour la fenêtre, définissez les mêmes arguments dans le hook :

add_filter('woot_vurgc_shortcode_data', function ($args) {
    if (isset($args['filter_provider']) && $args['filter_provider'] === 'woot_variations') {
        $args['per_page'] = 20;           // -1 shows all variations
        $args['per_page_position'] = 'b'; // pagination: t, b, tb or none
    }
    return $args;
});

Changer l’ordre de tri : par ID, par prix, comme dans l’éditeur de produit

La fenêtre trie les lignes dans le navigateur selon le contenu d’une cellule. Le tri par ID fonctionne directement, car la cellule d’ID contient un simple nombre :

add_filter('woot_vurgc_shortcode_data', function ($args) {
    if (isset($args['filter_provider']) && $args['filter_provider'] === 'woot_variations') {
        $args['orderby'] = 'id';
        $args['order'] = 'asc';
    }
    return $args;
});

La colonne ID doit figurer parmi les Colonnes des variations (Variations columns) pour que cela fonctionne, puisque les lignes ne contiennent que les champs sélectionnés ; pour la garder invisible, retirez-la de $args['columns'] dans le même hook, comme le fait l’exemple suivant avec sa colonne auxiliaire. Le tri par la colonne Prix (Price) ne donne pas le résultat attendu : la cellule de prix contient du HTML formaté avec le symbole monétaire, de sorte que les valeurs sont comparées comme du texte et que 105 arrive avant 12, et 12 avant 9. La méthode fiable consiste à utiliser une colonne auxiliaire contenant le nombre brut, servant au tri et gardée invisible :

// 1. A helper column with the price as a plain number
add_filter('woot_profile_extend', function ($profile, $action_name) {
    if ($action_name === 'woot_woocommerce_tables') {
        $profile['sort_price'] = [
            'title'   => 'Sort: price',
            'display' => false, // not offered in the Columns tab of regular tables
            'action'  => function ($post_id) {
                $product = WOOT_WooCommerce::get_product($post_id);
                return is_object($product) ? (float) $product->get_price() : 0;
            },
        ];
    }
    return $profile;
}, 10, 2);

// 2. Sort the popup by it and hide the helper column
add_filter('woot_vurgc_shortcode_data', function ($args) {
    if (isset($args['filter_provider']) && $args['filter_provider'] === 'woot_variations') {
        $args['orderby'] = 'sort_price';
        $args['order'] = 'asc'; // 'desc' puts the most expensive first
        $args['columns'] = implode(',', array_diff(explode(',', $args['columns']), ['sort_price']));
    }
    return $args;
});

Après avoir ajouté le code, ajoutez Sort: price aux Colonnes des variations (Variations columns) dans les réglages, faute de quoi les lignes ne porteront pas le nombre. Pour l’ordre que vous définissez en faisant glisser les variations dans l’éditeur de produit, appliquez le même schéma avec une colonne auxiliaire qui renvoie (int) get_post_field('menu_order', $post_id).

Afficher les champs personnalisés des variations et les données du produit parent

Les champs ajoutés dans l’onglet Meta appartiennent à un seul tableau, et la fenêtre n’a pas d’ID de tableau ; ils n’apparaissent donc jamais dans les Colonnes des variations (Variations columns). Enregistrez plutôt la clé meta pour tous les tableaux, comme décrit dans comment ajouter une clé meta globalement à tous les shortcodes :

add_filter('woot_profile_extend', function ($profile, $action_name) {
    if ($action_name === 'woot_woocommerce_tables') {
        $meta_key = 'msrp'; // the meta key of your variation field
        $profile[$meta_key] = woot()->columns->meta->assemble_meta_for_system([
            'title'     => WOOT_Vocabulary::get('MSRP'),
            'meta_key'  => $meta_key,
            'meta_type' => 'text', // text, number or calendar
        ]);
    }
    return $profile;
}, 10, 2);

La nouvelle colonne apparaît dans les Colonnes des variations (Variations columns). Dans la fenêtre, chaque ligne lit le champ depuis la variation elle-même ; un champ enregistré par variation affiche donc sa propre valeur dans chaque ligne.

Les données du produit parent fonctionnent de la même façon, car une colonne personnalisée reçoit l’ID de la variation de la ligne. La colonne intégrée Miniature (Thumbnail) n’affiche que l’image propre à la variation ; la colonne ci-dessous affiche l’image de la variation ou, si elle n’en a pas, l’image du produit, puisque WooCommerce se rabat sur l’image du parent pour les variations :

add_filter('woot_profile_extend', function ($profile, $action_name) {
    if ($action_name === 'woot_woocommerce_tables') {
        $profile['image_or_parent'] = [
            'title'  => WOOT_Vocabulary::get('Image'),
            'action' => function ($post_id) {
                $product = WOOT_WooCommerce::get_product($post_id);
                $image_id = is_object($product) ? $product->get_image_id() : 0;
                $src = $image_id ? wp_get_attachment_image_src($image_id, 'thumbnail') : false;
                return $src ? WOOT_HELPER::draw_html_item('img', ['src' => $src[0], 'width' => 60, 'alt' => '']) : '';
            },
        ];
    }
    return $profile;
}, 10, 2);

Pour toute autre donnée du parent, $product->get_parent_id() en donne l’ID.

Des colonnes différentes selon les rôles des utilisateurs

Le hook s’exécute à chaque requête de fenêtre, il peut donc vérifier qui regarde. Cette version masque les colonnes UGS (SKU) et stock à tout le monde, sauf à un rôle :

add_filter('woot_vurgc_shortcode_data', function ($args) {
    if (isset($args['filter_provider']) && $args['filter_provider'] === 'woot_variations') {
        $user = wp_get_current_user();
        if (!in_array('wholesale_customer', (array) $user->roles, true)) { // your role slug
            $args['columns'] = implode(',', array_diff(explode(',', $args['columns']), ['sku', 'stock_quantity']));
        }
    }
    return $args;
});

Une règle s’applique : les lignes sont préparées avant l’exécution du hook, à partir des champs sélectionnés dans les réglages. Sélectionnez donc dans les Colonnes des variations (Variations columns) toutes les colonnes que n’importe quel rôle peut voir, dans le bon ordre, et ne retirez des colonnes que dans le hook. Une colonne ajoutée dans le hook resterait vide, et une liste réordonnée placerait les en-têtes au-dessus des mauvaises cellules.

Ajout au panier et mise en forme

Chaque ligne possède son propre champ de quantité et son bouton Ajouter au panier (Add to cart). Une variation sans prix, ou en rupture de stock, n’a pas de bouton : WooCommerce ne la considère pas comme achetable, et le tableau suit cette règle. Un prix de 0 est un prix valide, le bouton reste donc affiché. Pour empêcher l’achat des variations à prix nul partout dans la boutique, fenêtre comprise :

add_filter('woocommerce_variation_is_purchasable', function ($purchasable, $variation) {
    if ((float) $variation->get_price() <= 0) {
        return false;
    }
    return $purchasable;
}, 10, 2);

Pour la mise en forme, un tableau de variations placé sur une page a la même structure et les mêmes classes que tout autre tableau, plus la classe woot_variations_columns. Les tableaux des fenêtres se trouvent dans .woot-content-in-popup. Chaque cellule porte la classe table23_td_ suivie de la clé du champ, et chaque en-tête a un attribut data-key. L’onglet CSS personnalisé (Custom CSS) d’un tableau n’atteint pas les fenêtres, qui n’ont pas d’ID de tableau ; placez donc les règles dans le champ de CSS personnalisé de votre thème :

/* Variations table on a page */
.woot_variations_columns .table23_td_price {
    font-weight: 600;
}

/* Tables in popups: variations, upsells, grouped */
.woot-content-in-popup th[data-key="stock_quantity"],
.woot-content-in-popup .table23_td_stock_quantity {
    text-align: center;
}

La fenêtre est demandée au serveur à chaque ouverture ; les modifications des réglages et du code apparaissent donc la prochaine fois qu’un visiteur clique sur le bouton. Vos questions sur une configuration précise sont les bienvenues sur le forum d’assistance de WOOT.