init_hooks(); } private function init_hooks(): void { // Components new AIREWP_Settings(); new AIREWP_Rewrite(); new AIREWP_Dashboard(); AIREWP_Setup::init(); // IndexNow new AIREWP_IndexNow(); // Generators new AIREWP_Agents_JSON(); new AIREWP_Agent_Card(); new AIREWP_LLMS_Txt(); new AIREWP_JSON_LD(); // REST API new AIREWP_REST_API(); // AI Bot Management in robots.txt (v3.0) new AIREWP_Robots_Txt(); // AI Crawler Analytics (v3.0) new AIREWP_Crawler_Analytics(); // WP Abilities API integration — WP 6.9+ (v3.0) new AIREWP_Abilities(); // v4.0 Modules new AIREWP_SEO(); // Suggested privacy policy text (Settings → Privacy) add_action( 'admin_init', [ $this, 'add_privacy_policy_content' ] ); // Regenerate files when settings or content change add_action( 'airewp_settings_updated', [ $this, 'regenerate_all' ] ); add_action( 'save_post', [ $this, 'on_content_change' ], 20, 2 ); add_action( 'delete_post', [ $this, 'schedule_regeneration' ] ); add_action( 'airewp_cron_regenerate', [ $this, 'regenerate_all' ] ); // Schedule daily regeneration if ( ! wp_next_scheduled( 'airewp_cron_regenerate' ) ) { wp_schedule_event( time(), 'daily', 'airewp_cron_regenerate' ); } } /** * Get plugin settings with defaults. */ public static function get_settings(): array { $defaults = [ // Business info 'company_name' => get_bloginfo( 'name' ), 'company_desc' => get_bloginfo( 'description' ), 'company_url' => home_url(), 'company_email' => get_option( 'admin_email' ), 'company_phone' => '', 'company_address' => '', 'company_city' => '', 'company_zip' => '', 'company_country' => '', 'company_logo' => '', 'industry' => 'general', 'languages' => [ get_locale() ], // Services (comma-separated) 'services' => '', // Social 'social_x' => '', 'social_linkedin' => '', 'social_instagram' => '', 'social_facebook' => '', 'social_github' => '', // Features toggles 'enable_agents_json' => true, 'enable_agent_card' => true, 'enable_llms_txt' => true, 'enable_json_ld' => true, 'enable_indexnow' => true, 'enable_rest_api' => true, 'enable_robots_ai' => true, // v3.0 'enable_crawler_analytics' => true, // v3.0 'enable_mcp_json' => false, // v4.2 // Robots.txt AI policy (v3.0) 'robots_block_training' => true, // Block training bots by default 'robots_block_retrieval' => false, // Allow retrieval/search bots // IndexNow 'indexnow_key' => '', // JSON-LD 'schema_type' => 'Organization', // Organization or LocalBusiness // v4.0 — SEO Module 'enable_seo' => true, // MCP servers (JSON array) 'mcp_servers' => '', // Advanced 'custom_tools' => '', 'custom_skills' => '', ]; $saved = get_option( AIREWP_OPTION_KEY, [] ); return wp_parse_args( $saved, $defaults ); } /** * Suggest privacy policy text (shown under Settings → Privacy). */ public function add_privacy_policy_content(): void { if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) { return; } $content = '
' . __( 'AI-Ready WP does not collect, store, or transmit personal data about your visitors. It does not set cookies and does not track human visitors.', 'ai-ready-wp' ) . '
'; $content .= '' . __( 'The AI Crawler Analytics feature counts visits from known AI bots based on their User-Agent string only; no IP addresses or other personal information are stored.', 'ai-ready-wp' ) . '
'; $content .= '' . __( 'When IndexNow is enabled, public URLs of your content are sent to the IndexNow API (api.indexnow.org) to notify search engines about updates. No visitor data is included in these requests.', 'ai-ready-wp' ) . '
'; $content .= '' . __( 'The generated discovery files (agents.json, agent-card.json, llms.txt) only contain the business information you enter in the plugin settings and public content from your site.', 'ai-ready-wp' ) . '
'; wp_add_privacy_policy_content( 'AI-Ready WP', wp_kses_post( wpautop( $content, false ) ) ); } /** * Regenerate all static files. */ public function regenerate_all(): void { $settings = self::get_settings(); // agents.json if ( $settings['enable_agents_json'] ) { AIREWP_Agents_JSON::generate( $settings ); } // agent-card.json if ( $settings['enable_agent_card'] ) { AIREWP_Agent_Card::generate( $settings ); } else { foreach ( [ 'agent-card.json', 'agent.json' ] as $card_name ) { $card_file = self::get_well_known_dir() . $card_name; self::delete_file( $card_file ); } } // llms.txt if ( $settings['enable_llms_txt'] ) { AIREWP_LLMS_Txt::generate( $settings ); } // mcp.json if ( $settings['enable_mcp_json'] ) { AIREWP_MCP_JSON::generate( $settings ); } else { self::delete_file( self::get_well_known_dir() . 'mcp.json' ); } // IndexNow if ( $settings['enable_indexnow'] && ! empty( $settings['indexnow_key'] ) ) { AIREWP_IndexNow::generate_key_file( $settings['indexnow_key'] ); } do_action( 'airewp_files_regenerated', $settings ); } /** * Handle content changes — regenerate files and ping IndexNow. */ public function on_content_change( int $post_id, \WP_Post $post ): void { // Skip revisions, autosaves, non-public post types if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { return; } if ( 'publish' !== $post->post_status ) { return; } $this->schedule_regeneration(); // Ping IndexNow for this specific URL $settings = self::get_settings(); if ( $settings['enable_indexnow'] && ! empty( $settings['indexnow_key'] ) ) { AIREWP_IndexNow::ping_url( get_permalink( $post_id ), $settings ); } } /** * Schedule a debounced regeneration (avoid running on every single save). */ public function schedule_regeneration(): void { if ( ! wp_next_scheduled( 'airewp_cron_regenerate' ) ) { wp_schedule_single_event( time() + 30, 'airewp_cron_regenerate' ); } } /** * Get the output directory for generated files. */ public static function get_output_dir(): string { return AIREWP_ROOT_PATH; } /** * Get the .well-known directory, creating it if needed. */ public static function get_well_known_dir(): string { $dir = AIREWP_ROOT_PATH . '.well-known/'; global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } if ( ! $wp_filesystem->is_dir( $dir ) ) { wp_mkdir_p( $dir ); } return $dir; } /** * Write a file using WP_Filesystem. */ public static function write_file( string $path, string $content ): bool { global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } return $wp_filesystem->put_contents( $path, $content, FS_CHMOD_FILE ); } /** * Delete a file using WP_Filesystem. */ public static function delete_file( string $path ): bool { global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } if ( $wp_filesystem->exists( $path ) ) { return $wp_filesystem->delete( $path ); } return true; } } // Activation register_activation_hook( __FILE__, function (): void { // Generate IndexNow key on activation $settings = AI_Ready_WP::get_settings(); if ( empty( $settings['indexnow_key'] ) ) { $settings['indexnow_key'] = bin2hex( random_bytes( 32 ) ); update_option( AIREWP_OPTION_KEY, $settings ); } // Flush rewrite rules AIREWP_Rewrite::add_rules(); flush_rewrite_rules(); // Generate all files AI_Ready_WP::instance()->regenerate_all(); // Trigger the first-run setup wizard on the next admin load. AIREWP_Setup::flag_activation(); } ); // Deactivation register_deactivation_hook( __FILE__, function (): void { wp_clear_scheduled_hook( 'airewp_cron_regenerate' ); flush_rewrite_rules(); } ); // Boot AI_Ready_WP::instance();