query_vars['airewp_file'] ?? ''; if ( empty( $file ) ) { return; } $settings = AI_Ready_WP::get_settings(); switch ( $file ) { case 'agents-json': if ( ! $settings['enable_agents_json'] ) { return; } $this->serve_json_file( '.well-known/agents.json' ); break; case 'agent-card-json': if ( ! $settings['enable_agent_card'] ) { $this->send_404(); return; } $this->serve_json_file( '.well-known/agent-card.json' ); break; case 'agent-json': if ( ! $settings['enable_agent_card'] ) { $this->send_404(); return; } $this->serve_json_file( '.well-known/agent.json' ); break; case 'llms-txt': if ( ! $settings['enable_llms_txt'] ) { return; } $this->serve_text_file( 'llms.txt' ); break; case 'llms-full-txt': if ( ! $settings['enable_llms_txt'] ) { return; } $this->serve_text_file( 'llms-full.txt' ); break; case 'indexnow-key': if ( ! $settings['enable_indexnow'] ) { $this->send_404(); return; } $key = $wp->query_vars['airewp_key'] ?? ''; if ( $key === $settings['indexnow_key'] ) { $this->send_text_response( $key ); } break; } } private function serve_json_file( string $path ): void { $file = AIREWP_ROOT_PATH . $path; global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } if ( ! $wp_filesystem->exists( $file ) ) { // Generate on-the-fly if missing AI_Ready_WP::instance()->regenerate_all(); } if ( $wp_filesystem->exists( $file ) ) { $content = $wp_filesystem->get_contents( $file ); if ( false !== $content ) { $decoded = json_decode( $content ); if ( null === $decoded ) { $this->send_404(); return; } $this->send_response_headers( 'json' ); echo wp_json_encode( $decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); exit; } } } private function serve_text_file( string $path ): void { $file = AIREWP_ROOT_PATH . $path; global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } if ( ! $wp_filesystem->exists( $file ) ) { AI_Ready_WP::instance()->regenerate_all(); } if ( $wp_filesystem->exists( $file ) ) { $content = $wp_filesystem->get_contents( $file ); if ( false !== $content ) { $this->send_response_headers( 'text' ); // Text content generated by this plugin, served as plain text (not HTML). echo wp_kses( $content, [] ); exit; } } } private function send_404(): void { status_header( 404 ); header( 'Content-Type: application/json' ); echo wp_json_encode( [ 'error' => 'Not found' ] ); exit; } /** * Send common response headers with whitelisted content type. */ private function send_response_headers( string $type ): void { $types = [ 'json' => 'application/json', 'text' => 'text/plain; charset=utf-8', ]; $content_type = $types[ $type ] ?? 'text/plain'; header( 'Content-Type: ' . $content_type ); header( 'Cache-Control: public, max-age=86400, stale-while-revalidate=604800' ); header( 'Access-Control-Allow-Origin: *' ); header( 'Access-Control-Allow-Methods: GET' ); header( 'X-Robots-Tag: noindex' ); } /** * Send a plain text response (for IndexNow key verification). */ private function send_text_response( string $content ): void { $this->send_response_headers( 'text' ); echo esc_html( $content ); exit; } }