load_referrer_library(); } /** * Charge la bibliothèque de référents depuis le fichier JSON */ private function load_referrer_library() { $json_path = ALMAWEB_PLUGIN_DIR . 'data/referrer-library.json'; if (!file_exists($json_path)) { return; } $json_content = file_get_contents($json_path); if ($json_content === false) { return; } $library = json_decode($json_content, true); if (json_last_error() !== JSON_ERROR_NONE || !isset($library['ai_referrers'])) { return; } $this->ai_referrers = $library['ai_referrers']; if (isset($library['version'])) { $this->library_version = $library['version']; } } /** * Détecte si le référent provient d'une plateforme IA * * @param string $referer_url URL du référent (HTTP_REFERER) * @return array|false Informations sur le référent IA ou false */ public function detect_ai_referrer($referer_url) { if (empty($referer_url) || empty($this->ai_referrers)) { return false; } // Nettoyer et parser l'URL. wp_parse_url() renvoie null pour un référent sans hôte // (chemin relatif, URL malformée) : ne jamais passer null à strtolower() (PHP 8.1+). $referer_host = wp_parse_url($referer_url, PHP_URL_HOST); if (!is_string($referer_host) || $referer_host === '') { return false; } $referer_host = strtolower($referer_host); // Retirer le 'www.' pour la comparaison if (substr($referer_host, 0, 4) === 'www.') { $referer_host = substr($referer_host, 4); } foreach ($this->ai_referrers as $ai_referrer) { $domain_to_check = strtolower((string) ($ai_referrer['domain'] ?? '')); if ($domain_to_check === '') { continue; } // Cas 1: Correspondance de domaine exacte (e.g., referer 'perplexity.ai' matches library 'perplexity.ai') if ($referer_host === $domain_to_check) { return $this->format_referrer_data($ai_referrer); } // Cas 2: Le référent est un sous-domaine du domaine de la bibliothèque // (e.g., referer 'chat.openai.com' matches library 'openai.com') $domain_suffix = '.' . $domain_to_check; // PHP 7.4 compatible str_ends_with if (substr($referer_host, -strlen($domain_suffix)) === $domain_suffix) { return $this->format_referrer_data($ai_referrer); } } return false; } /** * Formate les données du référent pour le retour * * @param array $ai_referrer * @return array */ private function format_referrer_data($ai_referrer) { return array( 'name' => $ai_referrer['name'], 'type' => $ai_referrer['type'], 'family' => $ai_referrer['family'], 'domain' => $ai_referrer['domain'], ); } /** * Vérifie si un référent est d'origine IA * * @param string $referer_url URL du référent * @return bool True si le référent est une plateforme IA */ public function is_ai_referrer($referer_url) { return $this->detect_ai_referrer($referer_url) !== false; } /** * Obtenir la version de la bibliothèque * * @return string Version */ public function get_library_version() { return $this->library_version; } /** * Obtenir le nombre de référents IA dans la bibliothèque * * @return int Nombre de référents */ public function get_referrers_count() { return count($this->ai_referrers); } /** * Obtenir la liste complète des référents IA * * @return array Liste des référents */ public function get_all_referrers() { return $this->ai_referrers; } /** * Détecte si la valeur utm_source provient d'une plateforme IA * * @param string $utm_source_value Valeur du paramètre utm_source * @return array|false Informations sur le référent IA ou false */ public function detect_ai_from_utm_source($utm_source_value) { if (empty($utm_source_value) || empty($this->ai_referrers)) { return false; } $source_lower = strtolower(trim((string) $utm_source_value)); foreach ($this->ai_referrers as $ai_referrer) { $domain_to_check = strtolower((string) ($ai_referrer['domain'] ?? '')); if ($domain_to_check === '') { continue; } // Cas 1: Correspondance exacte (e.g., utm_source 'perplexity.ai' matches library 'perplexity.ai') if ($source_lower === $domain_to_check) { return $this->format_referrer_data($ai_referrer); } // Cas 2: La source est un sous-domaine du domaine de la bibliothèque (e.g., 'chat.openai.com' matches 'openai.com') $domain_suffix = '.' . $domain_to_check; if (substr($source_lower, -strlen($domain_suffix)) === $domain_suffix) { return $this->format_referrer_data($ai_referrer); } // Cas 3: La source contient le nom de l'IA (e.g. 'chatgpt' matches 'ChatGPT Search') // Utile pour les cas où le utm_source n'est pas un domaine complet mais un nom if (strpos((string) ($ai_referrer['name'] ?? ''), $source_lower) !== false) { return $this->format_referrer_data($ai_referrer); } if (strpos($source_lower, strtolower((string) ($ai_referrer['family'] ?? ''))) !== false) { return $this->format_referrer_data($ai_referrer); } } return false; } }