J’ai créé une boutique en ligne pour un artiste, en utilisant l’extension Woocommerce, le thème Storefront et le thème enfant boutique. Il a fallu créer une extension pour ajouter quelques fonctionnalités ou éléments de style. Voici les explications.
Ce que je voulais ajouter
- Afficher le logo dans le header ;
- Remplacer la zone de recherche par un contenu fixe (coordonnées de l’auteur) ;
- utiliser les catégories médias de woocommerce dans enhanced media categories
- créer une galerie qui montre tous les produits vendus, sans le prix tout en ne voyant que les produits à vendre dans la boutique
- Voir l’image des objets achetés dans le chariot d’achat
L’extension complète est sur github. Ci-dessous, voici quelques explications.
Créer la structure de l’extension
Se référer à la série d’acticles « créer une extension de fonctionnalités« .
Afficher le logo dans le header
afficher un logo avec une fonctionnalité Jetpack
Initialement, le thème enfant (boutique) du thème principal (Storefront) n’affiche pas de logo, uniquement le titre du site et sa description.
J’ai découvert que le thème Storefront s’intégre avec Jetpack pour pouvoir afficher un logo. Le fichier storefront\inc\functions\setup.php contient en effet la ligne suivante :
add_theme_support( 'site-logo', array( 'size' => 'full' ) );
Pour plus d’informations sur cette fonctionnalité de Jetpack et la manière de l’intégrer à un thème, voir ce document en anglais.
Pour permettre le partage sur les réseaux sociaux, j’ai installé et activé Jetpack. Je n’ai laissé que les fonctionnalités suivantes :
- Enhanced Distribution
- JSON API
- Protect
- Publicize
- Sharing
- Site Stats
- WP.me Shortlinks
Une fois Jetpack activé, il devient possible de définir l’image à utiliser comme logo dans Apparence / Personnalisation / Titre et description ! Le logo apparaît mais il remplace le titre et la description.
Ajouter le titre et la description
Comme le thème storefront ne gère pas la possibilité d’ajouter le logo ET le titre et la description du site, j’ai dû créer cette fonctionnalité.
Cette partie est générée par le fichier includes/clea-patrice-header-logo.php
Voici le contenu :
add_action( 'init', 'clea_patrice_storefront_site_branding' ); /*************************************************** * * add a logo to the default storefront theme * see https://docs.woothemes.com/document/add-a-custom-logo/ ***************************************************/ if ( ! function_exists( 'clea_patrice_storefront_site_branding' ) ) { function clea_patrice_storefront_site_branding() { if ( function_exists( 'storefront_site_branding' ) ) { remove_action( 'storefront_header', 'storefront_site_branding', 20 ); } add_action( 'storefront_header', 'clea_storefront_display_custom_logo', 20 ); } } function clea_storefront_display_custom_logo() { ?> <div class="site-branding"> <?php if ( function_exists( 'jetpack_the_site_logo' ) ) jetpack_the_site_logo(); ?> <h1 class="site-title"><a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></h1> <?php if ( '' != get_bloginfo( 'description' ) ) { ?> <p class="site-description"><?php echo bloginfo( 'description' ); ?></p> <?php } ?> </div> <?php }
L’idée générale est d’éliminer le « action hook » initialement prévu pour ‘storefront header’ puis de le remettre avec une autre fonction.
Cette fonction ajoute le logo jetpack, le titre et la description du site dans le header.
Et le résultat est :
Remplacer la zone de recherche par un contenu fixe
Cette partie est générée par le fichier clea-patrice-functions.php
Enlever la barre de recherche
Ca se fait avec remove_action( ‘storefront_header’, ‘storefront_product_search’, 40 );
Ajouter un texte fixe
add_action( 'storefront_header', 'clea_patrice_storefront_header_content', 40 ); function clea_patrice_storefront_header_content() { ?> <div class="clea-adresse"> <p>Vous avez une question ? </p> <p><em>Contactez-moi (Patrice Poiraud) :</em></p> <p> <strong>00 00 00 00</strong> ou <strong><?php echo antispambot('mail@mail.com'); ?></strong></p> </div> <?php }
Catégories de photos
Attention, cette partie ne fonctionne que si l’on a installé et activé les plugins enhanced media category et Woocommerce. Ce serait plus élégant de vérifier qu’ils ont bien été activés avant avec is_plugin_active (voir le codex WordPress)
On peut facilement régler Enhanced Media Category pour que les images puissent prendre les catégories des produits, avec Media Settings / taxonomies. Mais Woocommerce ne montre pas ces catégories ensuite lorsqu’on veut insérer une image pour un produit.
Cette partie vient de la réponse apportée dans cette page en anglais du support WordPress. générée par le fichier clea-patrice-functions.php
add_action( 'wp_loaded', 'clea_patrice_show_img_cat'); function clea_patrice_show_img_cat() { // see https://wordpress.org/support/topic/product-category-in-the-library-dashboard global $wp_taxonomies; foreach ( get_taxonomies_for_attachments( 'object' ) as $taxonomy => $params ) { if ( in_array( 'attachment', $params->object_type ) && in_array( 'product', $params->object_type ) ) { // turns on taxonomy columns $wp_taxonomies[$taxonomy]->show_admin_column = 1; } } }
Et le résultat est exactement ce que je veux (voir test.css pour le style spécifique) :
Galerie de produits vendus
Ca a été très très difficile de trouver la solution. Mais c’est très simple en fait….
Je pouvais facilement ne voir que les produits à vendre dans la boutique en cochant ‘Cacher les produits en stock épuisé du catalogue’ dans Woocommerce / paramètres / Produits, onglet inventaires. Mais dans ce cas, impossible de créer une requête pour montrer les produits vendus dans une autre page.
Il a donc fallu que j’autorise de montrer les produits épuisés puis que je fasse des modifications pour que :
- dans la boutique, les produits épuisés ne sont pas montrés ;
- Dans la galerie, seuls les produits épuisés sont montrés.
Cette partie est générée par clea-patrice-soldout-page.php
Interdire l’affichage en boutique des produits déjà vendus
Je suis partie d’un article (en anglais) qui montrait comment modifier la requête woocommerce pour ne sélectionner que les produits en promotion. La fonction appelée, wc_get_product_ids_on_sale() , est une fonction woocommerce définie dans woocommerce/includes/wc-product-functions.php . Je m’en suis inspirée pour créer une fonction clea_patrice_get_in_stock_product_ids() qui récupère l’id de l’ensemble des produits en stock.
add_action( 'woocommerce_product_query', 'clea_patrice_instock_product_query' ); function clea_patrice_instock_product_query( $q ){ $product_ids_in_stock = clea_patrice_get_in_stock_product_ids(); $meta_query = WC()->query->get_meta_query(); $q->set( 'post__in', array_merge( array( 0 ), $product_ids_in_stock ) ); } function clea_patrice_get_in_stock_product_ids() { $in_stock = get_posts( array( 'post_type' => array( 'product', 'product_variation' ), 'posts_per_page' => -1, 'post_status' => 'publish', 'meta_query' => array( array( 'key' => '_visibility', 'value' => array('catalog', 'visible'), 'compare' => 'IN' ), array( 'key' => '_stock_status', 'value' => 'instock', 'compare' => '=' ) ), 'fields' => 'id=>parent' ) ); $product_ids = array_keys( $in_stock ); $parent_ids = array_values( array_filter( $in_stock ) ); $in_stock_product_ids = array_unique( array_merge( $product_ids, $parent_ids ) ); return $in_stock_product_ids; }
La fonction clea_patrice_instock_product_query( $q ) modifie la requête woocommerce pour qu’elle n’inclut que ce qui est retourné par la fonction clea_patrice_get_in_stock_product_ids() . Cette deuxième fonction récupère l’ensemble des produits visibles et en stock.
Mettre dans une page « galerie » tous les produits déjà vendus
Pour afficher les produits déjà vendus, j’ai créé un shortcode inspiré du snippet # 20 de cet article (en anglais). Je l’ai adapté pour qu’il affiche les produits en rupture de stock (outofstock) et non pas les produits en promotion. Maintenant, il suffit d’écrire [[produits_vendus]] dans une page pour que tous les produits vendus s’affichent comme dans la boutique.
Le code pour ce shortcode :
function clea_patrice_sold_out_shortcode( $atts ) { global $woocommerce_loop; extract(shortcode_atts(array( 'per_page' => '12', 'columns' => '3', 'orderby' => 'date', 'order' => 'desc' ), $atts)); $woocommerce_loop['columns'] = $columns; $args = array( 'post_type' => 'product', 'post_status' => 'publish', 'ignore_sticky_posts' => 1, 'posts_per_page' => $per_page, 'orderby' => $orderby, 'order' => $order, 'meta_query' => array( array( 'key' => '_visibility', 'value' => array('catalog', 'visible'), 'compare' => 'IN' ), array( 'key' => '_stock_status', 'value' => 'outofstock', 'compare' => '=' ) ) ); // Buffer our contents ob_start(); do_action( 'woocommerce_before_shop_loop' ); $loop = new WP_Query( $args ); if ( $loop->have_posts() ) { while ( $loop->have_posts() ) : $loop->the_post(); wc_get_template_part( 'content', 'product' ); endwhile; } else { echo __( 'No products found' ); } wp_reset_postdata(); do_action( 'woocommerce_after_shop_loop' ); // Return buffered contents return '<ul class="products">' . ob_get_clean() . '</ul>'; } add_shortcode('produits_vendus', 'clea_patrice_sold_out_shortcode');
J’ai également dû ajouter une fonction pour ajouter un badge « vendu » sur les produits vendus. Enfin, la feuille de style indique ‘display: none ; » pour les prix sur cette page galerie.
Pour voir les détails, voir includes/clea-patrice-soldout-page.php et css/test.php dans le dépôt Github.
C’est exactement ce que nous voulions :
Modifier le bouton « lire Plus » des produits vendus
Enfin presque ce que nous voulions. Le bouton « lire plus » sous les objets vendus n’a pas de sens. Il vaudrait mieux un texte du genre « plus de détails ».
Cette partie est visible dans le fichier clea-patrice-functions.php
Dans l’aide Woocommerce, il est question de deux filtres pour les boutons « add to cart ».
- Le premier, woocommerce_product_single_add_to_cart_text , permet de changer le texte des boutons « add to cart » dans les pages descriptives d’un produit.
- Le deuxième, woocommerce_product_add_to_cart_text fait la même chose pour les boutiques.
Il faut que je laisse à l’identique les boutons pour les produits à vendre, mais que je change celui des produits vendus de la galerie. Je vais donc utiliser le filtre woocommerce_product_add_to_cart_text , mais uniquement à condition que le produit soit vendu.
Pour la condition, j’ai utilisé la fonction get_post_custom( $product->ID ) que je ne connaissais pas.
Après quelques essais, j’ai pu déterminer que si je définissais :
$custom_fields = get_post_custom( $product->ID );
la variable $custom_fields[‘_stock_status’][0] me renvoyait outofstock pour les produits déjà vendus, instock pour les produits à vendre.
Et voilà ce qui permet de modifier les boutons de la galerie, mais pas de la boutique !
add_filter( 'woocommerce_product_add_to_cart_text', 'clea_patrice_sold_cart_button_text' ); // 2.1 + function clea_patrice_sold_cart_button_text() { $custom_fields = get_post_custom( $product->ID ); $term = $custom_fields['_stock_status'][0] ; // 'outofstock' or 'instock' if ( "outofstock" == $term ) { return __( 'Détails', 'woocommerce' ); } else { return __( 'Ajouter au Panier', 'woocommerce' ); } }
Et le résultat :
Ajouter l’image des produits dans le chariot
Voir l’image des objets achetés dans le chariot d’achat, c’est mieux pour l’acheteur. Il a plus confiance.
Pour celà, il suffisait simplement de modifier le style, ce que j’ai fait dans clea-patrice-add-functions/css/test.css :
table.cart .product-thumbnail { display: table-cell !important; } table.cart .product-thumbnail img { max-width: 2.618em; }
Et voilà !
Pour voir l’ensemble de l’extension, aller dans le dépôt Github.
Et si vous voulez voir le site de Patrice Poiraud, artiste à Nantes, c’est ici !