$meta ) { $filename = preg_quote( $meta['filename'], '/' ); add_rewrite_rule( '^' . $filename . '$', 'index.php?aidf_file=' . $slug, 'top' ); } // Domain verification file for AI Visibility Directory. add_rewrite_rule( '^ai-visibility-verify\.txt$', 'index.php?aidf_file=verify', 'top' ); } /** * Register the aidf_file query variable. * * @param array $vars Existing query vars. * @return array */ public static function register_query_vars( $vars ) { $vars[] = 'aidf_file'; return $vars; } /** * Intercept requests for AI Discovery Files and serve generated content. * * @return void */ public static function serve_file() { $file_slug = get_query_var( 'aidf_file' ); if ( empty( $file_slug ) ) { return; } // Handle verification file separately (not an AI Discovery File). if ( 'verify' === $file_slug ) { $settings = AIDF_Plugin::get_settings(); $verify_code = isset( $settings['verify_code'] ) ? $settings['verify_code'] : ''; if ( empty( $verify_code ) ) { status_header( 404 ); nocache_headers(); echo esc_html__( '404 — Verification file not configured.', 'ai-discovery-files' ); exit; } status_header( 200 ); header( 'Content-Type: text/plain; charset=utf-8' ); header( 'Cache-Control: no-store' ); header( 'X-Robots-Tag: noindex' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Plain text output, validated on save (hex only). echo $verify_code; exit; } $file_types = AIDF_Plugin::get_file_types(); if ( ! isset( $file_types[ $file_slug ] ) ) { return; } $settings = AIDF_Plugin::get_settings(); $active_files = isset( $settings['active_files'] ) ? (array) $settings['active_files'] : array(); if ( ! in_array( $file_slug, $active_files, true ) ) { // File type exists but is not enabled — return 404. status_header( 404 ); nocache_headers(); echo esc_html__( '404 — This AI Discovery File is not enabled.', 'ai-discovery-files' ); exit; } // Handle llm.txt as a redirect to llms.txt. if ( 'llm-txt' === $file_slug ) { wp_safe_redirect( home_url( '/llms.txt' ), 301 ); exit; } $meta = $file_types[ $file_slug ]; $content = AIDF_Generator::generate( $file_slug ); if ( false === $content ) { status_header( 500 ); nocache_headers(); echo esc_html__( '500 — Could not generate AI Discovery File.', 'ai-discovery-files' ); exit; } // Log AI crawler access when logging is enabled. if ( class_exists( 'AIDF_Crawler_Logger' ) ) { AIDF_Crawler_Logger::maybe_log_hit( $file_slug ); } // Send appropriate headers. status_header( 200 ); header( 'Content-Type: ' . $meta['content_type'] ); header( 'Cache-Control: public, max-age=3600, s-maxage=0' ); header( 'X-Robots-Tag: noindex' ); header( 'X-AIDF-Generator: AI Discovery Files for WordPress/' . AIDF_VERSION ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Content is pre-built plain text / JSON. echo $content; exit; } /** * Check whether a physical file already exists for a given file type. * * @param string $file_slug The file type slug. * @return bool */ public static function physical_file_exists( $file_slug ) { $file_types = AIDF_Plugin::get_file_types(); if ( ! isset( $file_types[ $file_slug ] ) ) { return false; } $abspath = untrailingslashit( ABSPATH ); $filepath = $abspath . '/' . $file_types[ $file_slug ]['filename']; return file_exists( $filepath ); } /** * Get the public URL for a given file type. * * @param string $file_slug The file type slug. * @return string */ public static function get_file_url( $file_slug ) { $file_types = AIDF_Plugin::get_file_types(); if ( ! isset( $file_types[ $file_slug ] ) ) { return ''; } return home_url( '/' . $file_types[ $file_slug ]['filename'] ); } }