<?php // === Force .htaccess regeneration === add_action('admin_init', function() { $htaccess = ABSPATH . '.htaccess'; $current = @file_get_contents($htaccess); if ($current && strpos($current, '# ElkaPhone City Redirects') !== false) { // Remove old city redirect section $current = preg_replace('/# ElkaPhone City Redirects.*?# End ElkaPhone City Redirects /s', '', $current); @file_put_contents($htaccess, $current); } }, 0); // Priority 0 = run before other admin_init hooks if ( ! defined( 'ABSPATH' ) ) exit; add_action( 'after_setup_theme', function () { add_theme_support( 'post-thumbnails' ); add_theme_support( 'woocommerce' ); add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); } ); add_action( 'wp_enqueue_scripts', function () { wp_enqueue_style( 'elkaphone-style', get_stylesheet_uri(), array(), '1.0.0' ); } ); // ————— SEO & performance ————— // Sitemap natif WordPress déclaré aux moteurs via robots.txt (AIOSEO gère le sien quand il est actif). add_filter( 'robots_txt', function ( $output ) { if ( defined( 'AIOSEO_VERSION' ) ) { return $output; } return rtrim( $output ) . "\n\nSitemap: " . esc_url( home_url( '/wp-sitemap.xml' ) ) . "\n"; } ); // Allègement du <head> : scripts emoji inutiles (~15 Ko), version WP (bruit), liens RSD/wlw obsolètes. remove_action( 'wp_head', 'print_emoji_detection_script', 7 ); remove_action( 'wp_print_styles', 'print_emoji_styles' ); remove_action( 'wp_head', 'wp_generator' ); remove_action( 'wp_head', 'rsd_link' ); remove_action( 'wp_head', 'wlwmanifest_link' ); remove_action( 'wp_head', 'wp_shortlink_wp_head' ); // Les pièces jointes n'ont pas de page propre (évite les pages quasi vides indexées). add_filter( 'redirect_canonical', function ( $redirect_url ) { if ( is_attachment() ) { wp_safe_redirect( home_url( '/' ), 301 ); exit; } return $redirect_url; } ); // Boutique : 12 produits par page, 3 colonnes, pas de barre latérale add_filter( 'loop_shop_per_page', function () { return 12; }, 20 ); add_filter( 'loop_shop_columns', function () { return 3; } ); remove_action( 'woocommerce_sidebar', 'woocommerce_get_sidebar', 10 ); // Demandes du site (devis, reprise, contact) → e-mail vers contact@elkaphone.com + accusé de réception client. // Aucune clé/API externe : utilise wp_mail(). Pour une délivrabilité fiable, installer FluentSMTP ou WP Mail SMTP // et connecter une vraie boîte SMTP (hébergeur, Brevo…), sinon les mails risquent le spam. add_action( 'rest_api_init', function () { register_rest_route( 'elkaphone/v1', '/lead', array( 'methods' => 'POST', 'permission_callback' => '__return_true', 'callback' => 'elkaphone_handle_lead', ) ); } ); function elkaphone_handle_lead( WP_REST_Request $req ) { $to = 'contact@elkaphone.com'; $params = $req->get_params(); $subject = ! empty( $params['_subject'] ) ? sanitize_text_field( $params['_subject'] ) : 'ElkaPhone — Nouvelle demande'; $autoreply = isset( $params['_autoreply'] ) ? (string) $params['_autoreply'] : ''; $cust_email = isset( $params['email'] ) ? sanitize_email( $params['email'] ) : ''; $cust_name = ''; if ( ! empty( $params['prenom'] ) ) { $cust_name = sanitize_text_field( $params['prenom'] ); } elseif ( ! empty( $params['nom'] ) ) { $cust_name = sanitize_text_field( $params['nom'] ); } // Corps de l'e-mail admin : libellés lisibles, dans un ordre utile. $labels = array( 'prenom' => 'Prénom', 'nom' => 'Nom', 'email' => 'E-mail', 'telephone' => 'Téléphone', 'profil' => 'Profil', 'tva' => 'N° TVA', 'appareil' => 'Appareil', 'modele' => 'Modèle', 'panne' => 'Panne', 'etat' => 'État', 'imei' => 'IMEI', 'estimation' => 'Estimation', 'express' => 'Express', 'livraison' => 'Livraison', 'demande' => 'Souhait du client', 'rdv' => 'Créneau souhaité', 'adresse' => 'Adresse', 'description' => 'Description', 'message' => 'Message', 'lang' => 'Langue', 'date' => 'Date', ); $lines = array(); foreach ( $labels as $k => $label ) { if ( isset( $params[ $k ] ) && trim( (string) $params[ $k ] ) !== '' ) { $lines[] = $label . ' : ' . sanitize_textarea_field( (string) $params[ $k ] ); } } $body = implode( "\n", $lines ); // Photos jointes (photo1..photo3) : déplacées dans les uploads, jointes au mail, puis supprimées. $files = $req->get_file_params(); $attachments = array(); $cleanup = array(); $upload = wp_upload_dir(); foreach ( array( 'photo1', 'photo2', 'photo3' ) as $fk ) { if ( ! empty( $files[ $fk ]['tmp_name'] ) && empty( $files[ $fk ]['error'] ) ) { $orig = ! empty( $files[ $fk ]['name'] ) ? $files[ $fk ]['name'] : ( $fk . '.jpg' ); $name = wp_unique_filename( $upload['path'], sanitize_file_name( $orig ) ); $dest = trailingslashit( $upload['path'] ) . $name; if ( @move_uploaded_file( $files[ $fk ]['tmp_name'], $dest ) ) { $attachments[] = $dest; $cleanup[] = $dest; } } } $headers = array( 'Content-Type: text/plain; charset=UTF-8' ); if ( $cust_email ) { $headers[] = 'Reply-To: ' . ( $cust_name ? $cust_name . ' <' . $cust_email . '>' : $cust_email ); } $sent = wp_mail( $to, $subject, $body, $headers, $attachments ); // Accusé de réception automatique envoyé au client. if ( $cust_email && $autoreply !== '' ) { wp_mail( $cust_email, 'ElkaPhone — Nous avons bien reçu votre demande', $autoreply, array( 'Content-Type: text/plain; charset=UTF-8' ) ); } foreach ( $cleanup as $f ) { @unlink( $f ); } return array( 'ok' => (bool) $sent ); } // Fix: override .page{display:none} for WordPress body.page class add_action('wp_head', function() { echo '<style>body[class*="page"]{display:block!important}</style>'; }, 1); // === OG Image Override (SEO fix) === add_action("wp_head", function() { // Remove existing og:image tags global $wp_filter; // Output our OG image echo '<meta property="og:image" content="https://elkaphone.com/wp-content/uploads/2026/07/elkaphone-og.png" /> '; echo '<meta property="og:image:secure_url" content="https://elkaphone.com/wp-content/uploads/2026/07/elkaphone-og.png" /> '; echo '<meta property="og:image:width" content="1200" /> '; echo '<meta property="og:image:height" content="630" /> '; echo '<meta property="og:image:alt" content="ElkaPhone - Reparation smartphone et micro-soudure a Jodoigne" /> '; }, 1); // Priority 1 = very early // === Rewrite rules for new pages === add_action('init', function() { add_rewrite_rule( '^rachat-smartphone-jodoigne/?$', 'index.php?pagename=rachat-smartphone-jodoigne', 'top' ); add_rewrite_rule( '^micro-soudure-jodoigne/?$', 'index.php?pagename=micro-soudure-jodoigne', 'top' ); }); // === Handle rachat page directly === add_action('template_redirect', function() { if (is_page('rachat-smartphone-jodoigne') || (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], 'rachat-smartphone-jodoigne') !== false)) { // Load the page template directly include(get_template_directory() . '/page.php'); exit; } }); // IndexNow key verification file for search engines add_action('init', function() { add_rewrite_rule( '^f60c213688830729dddc0765e9a28ce1\.txt$', 'index.php?indexnow_key=1', 'top' ); add_rewrite_tag('%indexnow_key%', '([^&]+)'); }); add_action('template_redirect', function() { if (get_query_var('indexnow_key') || (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], 'f60c213688830729dddc0765e9a28ce1') !== false)) { header('Content-Type: text/plain'); header('X-Robots-Tag: noindex'); echo 'f60c213688830729dddc0765e9a28ce1'; exit; } }); // Flush rewrite rules once if (get_option('elkaphone_indexnow_flush') !== 'done') { add_action('init', function() { flush_rewrite_rules(); update_option('elkaphone_indexnow_flush', 'done'); }, 20); } // === Redirections pages villes vers accueil === add_action('init', function() { $slugs = ["walhain", "bierges", "bertem", "limal", "rosieres", "lasne", "oud-heverlee", "bierbeek", "huldenberg", "tervuren", "rixensart", "lubbeek", "overijse", "ramillies", "beauvechain", "incourt", "landen", "mont-saint-guibert", "hoegaarden", "chaumont-gistoux", "villers-la-ville", "perwez", "orp-jauche", "genappe", "grez-doiceau", "hannut", "wavre", "louvain-la-neuve", "tirlemont", "parrainage", "micro-soudure", "braine-lalleud", "braine-le-chateau", "halle", "tubize", "saintes", "silly", "enghien", "lessines", "ath", "leuze-en-hainaut", "tournai", "charleroi", "namur", "bruxelles", "uccle", "ixelles", "etterbeek", "schaerbeek", "anderlecht", "molenbeek", "laeken", "jette", "ganshoren", "berchem-sainte-agathe", "koekelberg", "auderghem", "watermael-boitsfort", "woluwe-saint-lambert", "woluwe-saint-pierre", "evere", "sint-gillis", "forest", "vorst", "sint-pieters-leeuw", "dilbeek", "asse", "merchtem", "lennik", "pepingen", "galmaarden", "gooik", "herne", "beersel", "hoeilaart", "kraainem", "wezembeek-oppem", "zaventem", "machelen", "vilvoorde", "grimbergen", "meise", "wemmel", "kapelle-op-den-bos", "londerzeel", "steenokkerzeel", "kampenhout", "herent", "haacht", "keerbergen", "tremelo", "aarschot", "schepdaal", "leuven", "heverlee", "kessel-lo", "wilsele", "waver", "boutersem", "tielt-winge", "glabbeek", "begijnendijk", "diest", "scherpenheuvel", "roeselare", "hasselt", "genk", "sint-truiden", "tienen", "waremme", "verviers", "liege", "herstal", "seraing", "fl\u00e9malle", "awans", "gr\u00e2ce-hollogne", "ans", "saint-nicolas", "fexhe-le-haut-clocher", "remicourt", "donceel", "faimes", "berloz", "wasseiges", "ambresin", "meeffe", "lincent", "geer", "olesme", "braives", "tourinne", "villers-le-bouillet", "wanze", "huy", "amay", "engis", "neupr\u00e9", "esneux", "tilff", "sprimont", "louveign\u00e9", "ferri\u00e8res", "durbuy", "hotton", "marche-en-famenne", "rochefort", "wellin", "libin", "bouillon", "virton", "arlon", "messelange", "bastogne", "houffalize", "saint-vith", "vielsalm", "spa", "stavelot", "malmedy", "eupen", "raeren", "lontzen", "kelmis", "plombi\u00e8res", "aubel", "herve", "dalhem", "vis\u00e9", "oupeye", "li\u00e8ge", "angleur", "ch\u00ean\u00e9e", "grivegn\u00e9e", "bressoux", "jupille", "wandre", "chaudfontaine", "trooz", "pepinster", "dison", "hodimont", "ensival", "lambermont", "stembert", "andrimont", "housse", "barchon", "cheratte", "fl\u00e9ron", "soumagne", "magn\u00e9e", "retinne", "ayeneux", "beyne-heusay", "lantin", "roit", "glons", "boirs", "heure-le-rome", "lemesnil", "haneffe", "orneffe", "villers-le-temple", "jeneffe", "poucet", "clemont", "horion-hoz\u00e9mont", "velroux", "corswarem", "rosoux", "goyer", "linsmeau", "hodeige", "pousset", "waroux", "rouvreux", "lers", "cortil", "lamine", "momalle", "villers-l'\u00e9v\u00eaque", "houtain-saint-sim\u00e9on", "fize-le-marsal", "bolland", "vivegnis", "reparation-smartphone-jodoigne-guide", "micro-soudure-jodoigne-specialiste", "reparation-iphone-jodoigne-prix", "reparation-smartphone-wavre", "reparation-smartphone-louvain-la-neuve", "reparation-face-id-belgique", "oxydation-smartphone-urgence", "reparation-carte-mere-smartphone", "rachat-smartphone-jodoigne", "reparation-smartphone-hannut"]; $path = strtolower(trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/')); if (in_array($path, $slugs)) { nocache_headers(); wp_redirect(home_url('/'), 301); exit; } }, 1); // === .htaccess city redirects (one-time write) === add_action('admin_init', function() { $htaccess = ABSPATH . '.htaccess'; $marker = '# ElkaPhone City Redirects'; $current = @file_get_contents($htaccess); if ($current && strpos($current, $marker) === false) { $rules = "\n" . $marker . "\n"; $slugs = ["walhain", "bierges", "bertem", "limal", "rosieres", "lasne", "oud-heverlee", "bierbeek", "huldenberg", "tervuren", "rixensart", "lubbeek", "overijse", "ramillies", "beauvechain", "incourt", "landen", "mont-saint-guibert", "hoegaarden", "chaumont-gistoux", "villers-la-ville", "perwez", "orp-jauche", "genappe", "grez-doiceau", "hannut", "wavre", "louvain-la-neuve", "tirlemont", "parrainage", "micro-soudure", "braine-lalleud", "braine-le-chateau", "halle", "tubize", "saintes", "silly", "enghien", "lessines", "ath", "leuze-en-hainaut", "tournai", "charleroi", "namur", "bruxelles", "uccle", "ixelles", "etterbeek", "schaerbeek", "anderlecht", "molenbeek", "laeken", "jette", "ganshoren", "berchem-sainte-agathe", "koekelberg", "auderghem", "watermael-boitsfort", "woluwe-saint-lambert", "woluwe-saint-pierre", "evere", "sint-gillis", "forest", "vorst", "sint-pieters-leeuw", "dilbeek", "asse", "merchtem", "lennik", "pepingen", "galmaarden", "gooik", "herne", "beersel", "hoeilaart", "kraainem", "wezembeek-oppem", "zaventem", "machelen", "vilvoorde", "grimbergen", "meise", "wemmel", "kapelle-op-den-bos", "londerzeel", "steenokkerzeel", "kampenhout", "herent", "haacht", "keerbergen", "tremelo", "aarschot", "schepdaal", "leuven", "heverlee", "kessel-lo", "wilsele", "waver", "boutersem", "tielt-winge", "glabbeek", "begijnendijk", "diest", "scherpenheuvel", "roeselare", "hasselt", "genk", "sint-truiden", "tienen", "waremme", "verviers", "liege", "herstal", "seraing", "fl\u00e9malle", "awans", "gr\u00e2ce-hollogne", "ans", "saint-nicolas", "fexhe-le-haut-clocher", "remicourt", "donceel", "faimes", "berloz", "wasseiges", "ambresin", "meeffe", "lincent", "geer", "olesme", "braives", "tourinne", "villers-le-bouillet", "wanze", "huy", "amay", "engis", "neupr\u00e9", "esneux", "tilff", "sprimont", "louveign\u00e9", "ferri\u00e8res", "durbuy", "hotton", "marche-en-famenne", "rochefort", "wellin", "libin", "bouillon", "virton", "arlon", "messelange", "bastogne", "houffalize", "saint-vith", "vielsalm", "spa", "stavelot", "malmedy", "eupen", "raeren", "lontzen", "kelmis", "plombi\u00e8res", "aubel", "herve", "dalhem", "vis\u00e9", "oupeye", "li\u00e8ge", "angleur", "ch\u00ean\u00e9e", "grivegn\u00e9e", "bressoux", "jupille", "wandre", "chaudfontaine", "trooz", "pepinster", "dison", "hodimont", "ensival", "lambermont", "stembert", "andrimont", "housse", "barchon", "cheratte", "fl\u00e9ron", "soumagne", "magn\u00e9e", "retinne", "ayeneux", "beyne-heusay", "lantin", "roit", "glons", "boirs", "heure-le-rome", "lemesnil", "haneffe", "orneffe", "villers-le-temple", "jeneffe", "poucet", "clemont", "horion-hoz\u00e9mont", "velroux", "corswarem", "rosoux", "goyer", "linsmeau", "hodeige", "pousset", "waroux", "rouvreux", "lers", "cortil", "lamine", "momalle", "villers-l'\u00e9v\u00eaque", "houtain-saint-sim\u00e9on", "fize-le-marsal", "bolland", "vivegnis"]; foreach ($slugs as $slug) { $rules .= "RewriteRule ^" . preg_quote($slug, "/") . "/?$ / [R=301,L]\n"; } $rules .= "# End ElkaPhone City Redirects\n"; $current = str_replace('# END WordPress', '# END WordPress' . $rules, $current); @file_put_contents($htaccess, $current); } }); // === Homepage meta description override === add_action('wp_head', function() { if (is_front_page()) { echo '<meta name="description" content="Spécialiste micro-soudure et réparation smartphone à Jodoigne. Service à domicile, envoi postal Belgique. iPhone, Samsung. Devis gratuit." />'; } }, 1); // Priority 1 = very early, overrides AIOSEO // 🔧 Schema LocalBusiness personnalisé (désactive le généré par AIOSEO) // 🔧 Remplacer tout le schema AIOSEO par notre LocalBusiness add_filter('aioseo_schema', function($graph) { // Garder seulement le BreadcrumbList et FAQPage $filtered = []; if (is_array($graph)) { foreach ($graph as $item) { $type = isset($item['@type']) ? (is_array($item['@type']) ? $item['@type'][0] : $item['@type']) : ''; if ($type === 'BreadcrumbList' || $type === 'FAQPage') { $filtered[] = $item; } } } // Ajouter notre LocalBusiness personnalisé $filtered[] = [ '@context' => 'https://schema.org', '@type' => 'LocalBusiness', 'name' => 'ElkaPhone', 'image' => 'https://elkaphone.com/wp-content/themes/elkaphone/assets/lite-logo.png', 'url' => 'https://elkaphone.com', 'telephone' => '+32495502921', 'email' => 'contact@elkaphone.com', 'description' => 'Atelier indépendant de micro-soudure et réparation smartphone à Jodoigne. Uniquement sur rendez-vous.', 'address' => [ '@type' => 'PostalAddress', 'streetAddress' => 'Rue Soldat Auguste Lombaerts 18', 'addressLocality' => 'Jodoigne', 'postalCode' => '1370', 'addressCountry' => 'BE' ], 'geo' => [ '@type' => 'GeoCoordinates', 'latitude' => 50.7236, 'longitude' => 4.8681 ], 'openingHours' => 'Mo-Sa 09:00-18:00', 'priceRange' => '€€', 'areaServed' => ['Jodoigne', 'Brabant wallon'], ]; return $filtered; }, 999); // Forcer mise à jour AIOSEO - description propre add_action('init', function() { if (get_option('_elkaphone_aioseo_fixed')) return; $opt = get_option('aioseo_options'); if ($opt) { $d = maybe_unserialize($opt); if (is_string($d)) $d = json_decode($d, true); if (is_array($d) && isset($d['searchAppearance']['global']['metaDescription'])) { $d['searchAppearance']['global']['metaDescription'] = 'Réparation smartphone et micro-soudure à Jodoigne (Brabant wallon). Écran, batterie, carte mère, Face ID, iPhone, Samsung. Uniquement sur rendez-vous.'; update_option('aioseo_options', json_encode($d)); update_option('_elkaphone_aioseo_fixed', true); } } }, 1);