init(); } /** * Initialize plugin */ private function init() { // Check if we need to flush rewrite rules (after activation) if (get_option('ai_ready_core_activated')) { add_action('init', function() { delete_option('ai_ready_core_activated'); flush_rewrite_rules(); }, 20); } // Hook into WordPress initialization add_action('init', [$this, 'setup_rewrite_rules']); add_action('template_redirect', [$this, 'handle_llms_txt_request']); // Prevent 404 for llms.txt requests add_filter('pre_handle_404', function($preempt, $wp_query) { if (isset($wp_query->query_vars['ai_ready_llms_txt'])) { return true; } return $preempt; }, 10, 2); // Hook into content changes to auto-refresh llms.txt add_action('save_post', [$this, 'on_content_change']); add_action('delete_post', [$this, 'on_content_change']); add_action('wp_trash_post', [$this, 'on_content_change']); add_action('untrash_post', [$this, 'on_content_change']); add_action('transition_post_status', [$this, 'on_post_status_change'], 10, 3); add_action('ai_ready_delayed_refresh', [$this, 'on_delayed_refresh']); // Agent Gate module will handle robots.txt filtering // Include required files $this->include_files(); // Load translation strings $this->load_translation_strings(); // Initialize modules and admin $this->init_modules(); } /** * Load translation strings */ private function load_translation_strings() { $strings_file = AI_READY_CORE_PLUGIN_DIR . 'includes/ai-ready-strings.php'; if (file_exists($strings_file)) { require_once $strings_file; } else { $this->debug_log('Translation strings file not found: ' . $strings_file); } } /** * Initialize modules and admin components */ private function init_modules() { global $ai_ready_agent_gate; // Initialize Agent Gate module if (class_exists('AI_Ready_Agent_Gate')) { $ai_ready_agent_gate = new AI_Ready_Agent_Gate(); } else { $ai_ready_agent_gate = null; $this->debug_log('Agent Gate class not found'); } // Initialize admin with Agent Gate module if in admin area if (is_admin() && class_exists('AI_Ready_Admin')) { new AI_Ready_Admin($ai_ready_agent_gate); } } /** * Include required plugin files */ private function include_files() { // Include core files when they exist $includes_dir = AI_READY_CORE_PLUGIN_DIR . 'includes/'; $generator_file = $includes_dir . 'llms-generator.php'; if (file_exists($generator_file)) { require_once $generator_file; } else { $this->debug_log('Generator file not found: ' . $generator_file); } $diagnostics_file = $includes_dir . 'diagnostics.php'; if (file_exists($diagnostics_file)) { require_once $diagnostics_file; } else { $this->debug_log('Diagnostics file not found: ' . $diagnostics_file); } // Load Agent Gate module $agent_gate_file = $includes_dir . 'modules/agent-gate/class-ai-ready-agent-gate.php'; if (file_exists($agent_gate_file)) { require_once $agent_gate_file; } else { $this->debug_log('Agent Gate module not found: ' . $agent_gate_file); } // Load new admin component structure $admin_file = $includes_dir . 'admin/class-ai-ready-admin.php'; if (file_exists($admin_file)) { require_once $admin_file; } else { $this->debug_log('Admin file not found: ' . $admin_file); } } /** * Debug logging helper - only logs when WP_DEBUG is enabled */ private function debug_log($message) { self::log($message, 'debug'); } /** * Setup rewrite rules for llms.txt endpoint */ public function setup_rewrite_rules() { // Add rewrite rule for llms.txt (both with and without trailing slash) add_rewrite_rule('^llms\.txt/?$', 'index.php?ai_ready_llms_txt=1', 'top'); // Add query var add_filter('query_vars', [$this, 'add_query_vars']); } /** * Add custom query vars */ public function add_query_vars($vars) { $vars[] = 'ai_ready_llms_txt'; return $vars; } /** * Handle llms.txt virtual page request */ public function handle_llms_txt_request() { global $wp_query; if (get_query_var('ai_ready_llms_txt')) { // Set proper headers header('Content-Type: text/plain; charset=utf-8'); // Prevent 404 status status_header(200); // Set WP Query vars to prevent default handling $wp_query->is_404 = false; $wp_query->is_page = true; // Generate and output llms.txt content $content = $this->generate_llms_txt_content(); echo esc_html($content); // Exit to prevent WordPress from loading the theme exit; } } /** * Generate llms.txt content * This is a basic implementation that will be enhanced by llms-generator.php */ private function generate_llms_txt_content() { // If llms-generator.php is loaded and has the enhanced function, use it if (function_exists('ai_ready_generate_llms_txt_enhanced')) { try { return ai_ready_generate_llms_txt_enhanced(); } catch (Exception $e) { $this->debug_log('Exception in enhanced generator: ' . $e->getMessage()); // Fall through to basic implementation } } // Basic fallback implementation $site_name = get_bloginfo('name'); $content = "# {$site_name}\n\n"; // Basic docs section $content .= "## Docs\n\n"; $content .= "- [Home](" . home_url() . "): Website homepage\n"; return $content; } /** * Handle content changes (posts/pages published, updated, deleted) */ public function on_content_change($post_id) { // Only process published posts and pages $post = get_post($post_id); if (!$post || !in_array($post->post_type, ['post', 'page'])) { return; } // Schedule delayed refresh to ensure post data is fully saved wp_schedule_single_event(time() + 5, 'ai_ready_delayed_refresh', [$post_id]); // Also do immediate refresh for most cases $this->refresh_llms_txt_cache(); } /** * Handle post status transitions (draft to publish, etc.) */ public function on_post_status_change($new_status, $old_status, $post) { // Only process when status changes involving 'publish' if (!in_array($post->post_type, ['post', 'page'])) { return; } if ($new_status === 'publish' || $old_status === 'publish') { $this->refresh_llms_txt_cache(); } } /** * Handle delayed refresh after content changes */ public function on_delayed_refresh($post_id) { $this->refresh_llms_txt_cache(); // Clear additional caches that might be affecting page discovery wp_cache_flush(); } /** * Refresh the llms.txt cache by clearing cached sections */ private function refresh_llms_txt_cache() { if (function_exists('ai_ready_force_refresh_sections')) { ai_ready_force_refresh_sections(); } // Also clear WordPress sitemap cache to ensure fresh data if (function_exists('ai_ready_refresh_sitemap')) { ai_ready_refresh_sitemap(); } // Clear WordPress object cache to ensure fresh page queries wp_cache_flush(); } /** * Plugin activation hook */ public static function activate() { // First add the rewrite rules add_rewrite_rule('^llms\.txt/?$', 'index.php?ai_ready_llms_txt=1', 'top'); // Register the query var add_filter('query_vars', function($vars) { $vars[] = 'ai_ready_llms_txt'; return $vars; }); // Store activation time to ensure rules are flushed on next request update_option('ai_ready_core_activated', time()); // Clear any disabled state from previous issues delete_option('ai_ready_llms_disabled'); // Initialize defaults if (function_exists('ai_ready_init_llms_defaults')) { ai_ready_init_llms_defaults(); } // Log activation self::log('Plugin activated', 'info'); // Initialize Agent Gate if available $agent_gate_file = plugin_dir_path(__FILE__) . 'includes/modules/agent-gate/class-ai-ready-agent-gate.php'; if (file_exists($agent_gate_file)) { require_once $agent_gate_file; if (class_exists('AI_Ready_Agent_Gate')) { AI_Ready_Agent_Gate::on_plugin_activation(); } } // Trigger activation action for other components do_action('ai_ready_core_activated'); // Flush rewrite rules after everything is set up flush_rewrite_rules(); } /** * Plugin deactivation hook */ public static function deactivate() { // Flush rewrite rules to clean up our endpoint flush_rewrite_rules(); // Log deactivation self::log('Plugin deactivated', 'info'); } /** * Plugin uninstall hook */ public static function uninstall() { // Clean up options delete_option('ai_ready_llms_sections'); delete_option('ai_ready_llms_notes'); delete_option('ai_ready_site_title'); delete_option('ai_ready_site_summary'); delete_option('ai_ready_custom_content'); delete_option('ai_ready_llms_disabled'); delete_option('ai_ready_last_section_refresh'); // Clean up Agent Gate settings using module if (class_exists('AI_Ready_Agent_Gate')) { AI_Ready_Agent_Gate::cleanup_settings(); } else { // Fallback cleanup if module not available delete_option('ai_ready_agent_gate_mode'); delete_option('ai_ready_agent_gate_custom'); delete_option('ai_ready_original_robots_txt'); } // Clear any cached content delete_transient('ai_ready_diagnostics_cache'); // Remove scheduled events wp_clear_scheduled_hook('ai_ready_delayed_refresh'); // Flush rewrite rules flush_rewrite_rules(); // Log uninstall self::log('Plugin uninstalled', 'info'); } } // Register activation and deactivation hooks register_activation_hook(__FILE__, function() { AI_Ready_Core::activate(); do_action('ai_ready_core_activated'); }); register_deactivation_hook(__FILE__, ['AI_Ready_Core', 'deactivate']); // Initialize the plugin AI_Ready_Core::getInstance();