pick_variant_for_request( (int) $post_id ); if ( is_array( $picked ) && ! empty( $picked['json'] ) ) { $json = (string) $picked['json']; $ab_variant_marker = sprintf( ' (A/B test #%d, variant %s)', (int) $picked['test_id'], (string) $picked['variant'] ); $decoded = json_decode( $json, true ); if ( null !== $decoded ) { echo "\n\n"; echo '' . "\n"; } return; } } // Lecture du schema stocké en DB (déjà généré par cron / AJAX admin). $cache_key = 'aiforya_sm_schema_' . $post_id; $json = get_transient( $cache_key ); if ( false === $json ) { // Pas de cache → tente lecture DB (sans appel LLM). if ( class_exists( 'Aiforya_Schema_Markup_Db' ) ) { $db = Aiforya_Schema_Markup_Db::get_instance(); $schema = method_exists( $db, 'get_active_schema_for_post' ) ? $db->get_active_schema_for_post( $post_id ) : null; if ( is_array( $schema ) && ! empty( $schema['schema_json'] ) ) { $json = (string) $schema['schema_json']; $ttl = (int) ( $settings['cache_ttl_minutes'] ?? 1440 ) * MINUTE_IN_SECONDS; set_transient( $cache_key, $json, max( 300, $ttl ) ); } } } if ( ! is_string( $json ) || '' === $json ) { return; } // Validation JSON minimale avant injection. $decoded = json_decode( $json, true ); if ( null === $decoded ) { return; } // F12 — WPML/Polylang : ajout auto du champ inLanguage si absent. $decoded = $this->maybe_add_in_language( $decoded, $post_id ); $json = wp_json_encode( $decoded, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); echo "\n\n"; echo '' . "\n"; // Multi-schema : injecte les schémas additionnels (slot != 'primary') si activés pour ce post. $this->maybe_inject_secondary_schemas( $post_id ); } /** * F12 — Détection langue WPML/Polylang/site et ajout du champ inLanguage. */ private function maybe_add_in_language( array $data, int $post_id ): array { if ( isset( $data['inLanguage'] ) ) return $data; $lang = ''; // WPML if ( function_exists( 'apply_filters' ) ) { // This is WPML's own public API hook: the name is imposed by WPML and must not be // prefixed, otherwise WPML would never answer. We consume it, we do not define it. // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- third-party hook defined by WPML; renaming it would break the integration. $wpml = apply_filters( 'wpml_post_language_details', null, $post_id ); if ( is_array( $wpml ) && ! empty( $wpml['language_code'] ) ) { $lang = (string) $wpml['language_code']; } } // Polylang if ( $lang === '' && function_exists( 'pll_get_post_language' ) ) { $pll = pll_get_post_language( $post_id ); if ( is_string( $pll ) && $pll !== '' ) $lang = $pll; } // Fallback site default if ( $lang === '' ) { $site_lang = get_bloginfo( 'language' ); if ( is_string( $site_lang ) && $site_lang !== '' ) $lang = strtolower( substr( $site_lang, 0, 2 ) ); } if ( $lang !== '' ) $data['inLanguage'] = $lang; return $data; } /** * Multi-schema per post — injecte les schémas additionnels stockés avec slot != 'primary'. * Doctrine PRIO 10 : lecture seule DB, pas d'appel LLM. */ private function maybe_inject_secondary_schemas( int $post_id ): void { global $wpdb; $table = $wpdb->prefix . 'aiforya_sm_schemas'; $rows = $wpdb->get_results( $wpdb->prepare( "SELECT schema_json FROM %i WHERE post_id = %d AND status = 'active' AND is_primary = 0 LIMIT 5", $table, $post_id ) ); if ( empty( $rows ) ) return; foreach ( $rows as $r ) { $json = (string) ( $r->schema_json ?? '' ); if ( $json === '' ) continue; $decoded = json_decode( $json, true ); if ( null === $decoded ) continue; $decoded = $this->maybe_add_in_language( $decoded, $post_id ); $json = wp_json_encode( $decoded, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); echo "\n\n"; echo '' . "\n"; } } }