PHP_VERSION, 'wp_version' => get_bloginfo( 'version' ), 'plugin_version' => WP_AI_WORKFLOWS_PRO_VERSION, 'memory_limit' => ini_get( 'memory_limit' ), 'max_execution_time' => ini_get( 'max_execution_time' ), 'active_plugins' => get_option( 'active_plugins' ), 'is_multisite' => is_multisite(), 'db_version' => get_option( WP_AI_WORKFLOWS_DB_VERSION_OPTION ), ) ); WP_AI_Workflows_Utilities::debug_log( 'Caching configuration', 'info', array( 'wp_cache' => defined( 'WP_CACHE' ) && WP_CACHE, 'cache_plugins' => array_filter( get_option( 'active_plugins' ), function ( $plugin ) { return strpos( $plugin, 'cache' ) !== false; } ), 'permalinks' => get_option( 'permalink_structure' ), 'rest_enabled' => get_option( 'permalink_structure' ) !== '', 'htaccess_writable' => is_writable( ABSPATH . '.htaccess' ), 'rest_base' => rest_get_url_prefix(), ) ); // Test for potential reverse proxy/CDN issues WP_AI_Workflows_Utilities::debug_log( 'Server configuration', 'info', array( 'server_software' => 'redacted', // Removed for security 'is_ssl' => is_ssl(), 'proxy_headers' => array_filter( $_SERVER, function ( $key ) { return strpos( $key, 'HTTP_X_' ) === 0 || strpos( $key, 'HTTP_CF_' ) === 0 || strpos( $key, 'HTTP_CLOUDFRONT_' ) === 0; }, ARRAY_FILTER_USE_KEY ), ) ); global $wpdb; WP_AI_Workflows_Utilities::debug_log( 'Database pre-activation state', 'info', array( 'db_prefix' => $wpdb->prefix, 'db_charset' => $wpdb->charset, 'db_collate' => $wpdb->collate, 'existing_tables' => $wpdb->get_col( $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->prefix . 'wp_ai_workflows%' ) ), 'mysql_version' => $wpdb->db_version(), ) ); // Deactivate any active legacy Lite/Pro copy up front so it cannot clash // with v2.0 on subsequent loads (mirrors the admin_init scan). WP_AI_Workflows_Legacy_Guard::scan_and_deactivate(); WP_AI_Workflows_Database::create_tables(); WP_AI_Workflows_Utilities::generate_and_encrypt_api_key(); wp_ai_workflows_schedule_cleanup_cron(); delete_option( 'wp_ai_workflows_human_tasks_db_version' ); update_option( WP_AI_WORKFLOWS_DB_VERSION_OPTION, WP_AI_WORKFLOWS_PRO_VERSION ); wp_ai_workflows_setup_files(); WP_AI_Workflows_Cost_Management::get_instance()->initialize_cost_settings(); // Usage analytics are OPT-IN and OFF by default: do NOT enable telemetry on // activation. Nothing is sent unless the site owner explicitly turns on the // `wp_ai_workflows_analytics_opt_in` option in Settings. Clear any stale // telemetry cron left behind by a previous (opt-out era) install. if ( ! get_option( 'wp_ai_workflows_analytics_opt_in', false ) ) { wp_clear_scheduled_hook( 'wp_ai_workflows_daily_analytics' ); } if ( ! wp_next_scheduled( 'wp_ai_workflows_cleanup_chat_data' ) ) { wp_schedule_event( time(), 'daily', 'wp_ai_workflows_cleanup_chat_data' ); } if ( ! wp_next_scheduled( 'wp_ai_workflows_daily_maintenance' ) ) { wp_schedule_event( time(), 'daily', 'wp_ai_workflows_daily_maintenance' ); } $admin_role = get_role( 'administrator' ); if ( $admin_role ) { $admin_role->add_cap( 'manage_workflow_tasks' ); } if ( ! get_option( 'wp_ai_workflows_task_roles' ) ) { update_option( 'wp_ai_workflows_task_roles', array( 'administrator' ) ); } add_option( 'wp_ai_workflows_setup_completed', false ); WP_AI_Workflows_Utilities::debug_log( 'Database post-activation state', 'info', array( 'tables_after' => $wpdb->get_col( $wpdb->prepare( "SHOW TABLES LIKE %s", $wpdb->prefix . 'wp_ai_workflows%' ) ), ) ); WP_AI_Workflows_Utilities::debug_log( 'Plugin activation completed successfully', 'info' ); $output = ob_get_clean(); if ( ! empty( $output ) ) { error_log( 'WP AI Workflows activation output: ' . $output ); } } catch ( Exception $e ) { ob_end_clean(); WP_AI_Workflows_Utilities::debug_log( 'Activation failed', 'error', array( 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ) ); error_log( 'WP AI Workflows activation error: ' . $e->getMessage() ); throw $e; } finally { delete_transient( $lock_key ); } } function wp_ai_workflows_migrate_license_data() { if ( get_option( 'wp_ai_workflows_license_migrated', false ) ) { return; } WP_AI_Workflows_License_Security::maybe_migrate_license_data(); update_option( 'wp_ai_workflows_license_migrated', true ); WP_AI_Workflows_Utilities::debug_log( 'License data migration attempted during update', 'info' ); } /** * Plugin deactivation */ function deactivate_wp_ai_workflows() { ob_start(); try { set_transient( 'wp_ai_workflows_maintenance_mode', true, 300 ); wp_clear_scheduled_hook( 'wp_ai_workflows_cleanup' ); wp_clear_scheduled_hook( 'wp_ai_workflows_cleanup_chat_data' ); wp_clear_scheduled_hook( 'wp_ai_workflows_check_license' ); wp_clear_scheduled_hook( 'wp_ai_workflows_daily_maintenance' ); wp_clear_scheduled_hook( 'wp_ai_workflows_license_verify' ); global $wpdb; // Pattern for temporary license cache entries $pattern = '^wp_ai_workflows_lic_[a-f0-9]{8}$'; $cache_count = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name REGEXP %s", $pattern ) ); if ( $cache_count > 0 ) { WP_AI_Workflows_Utilities::debug_log( 'Database optimization completed', 'info', array( 'entries_processed' => $cache_count, ) ); } WP_AI_Workflows_Utilities::debug_log( 'Plugin deactivated successfully' ); delete_transient( 'wp_ai_workflows_maintenance_mode' ); $output = ob_get_clean(); if ( ! empty( $output ) ) { error_log( 'WP AI Workflows deactivation output: ' . $output ); } } catch ( Exception $e ) { delete_transient( 'wp_ai_workflows_maintenance_mode' ); ob_end_clean(); error_log( 'WP AI Workflows deactivation error: ' . $e->getMessage() ); } } register_activation_hook( __FILE__, 'activate_wp_ai_workflows' ); register_activation_hook( __FILE__, 'wp_ai_workflows_migrate_license_data' ); register_deactivation_hook( __FILE__, 'deactivate_wp_ai_workflows' ); /** * Increase execution time for plugin operations */ function wp_ai_workflows_increase_execution_time() { $action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ?? '' ) ); if ( $action && strpos( $action, 'wp-ai-workflows' ) !== false ) { ini_set( 'max_execution_time', 300 ); set_time_limit( 300 ); } } add_action( 'init', 'wp_ai_workflows_increase_execution_time' ); /** * Main plugin initialization */ function run_wp_ai_workflows() { ob_start(); try { $license = new WP_AI_Workflows_License(); WP_AI_Workflows_License_Security::init(); $components = array( new WP_AI_Workflows_REST_API(), new WP_AI_Workflows_Admin(), new WP_AI_Workflows_Database(), new WP_AI_Workflows_Analytics_Collector( WP_AI_WORKFLOWS_PRO_VERSION, true ), ); foreach ( $components as $component ) { $component->init(); } WP_AI_Workflows_Encryption::init(); WP_AI_Workflows_Platform_Client::init(); // Phase 3 (R6.1/R6.5): free-first. The plugin ALWAYS initializes full // functionality — the SLM license no longer gates the plugin, and no // license phone-home runs on load (wp.org Guideline 6). Premium/Cloud // features gate on platform connection state, not a license. The license // classes remain as a dormant fallback but are not consulted here. WP_AI_Workflows_Updater::get_instance(); WP_AI_Workflows_WPOrg_Migration::get_instance(); initialize_full_functionality( $license ); $is_connected = WP_AI_Workflows_Platform_Client::is_connected(); add_filter( 'wp_ai_workflows_frontend_settings', function ( $settings ) use ( $is_connected ) { // Kept key name for frontend back-compat; now reflects connection state. $settings['license_active'] = $is_connected; $settings['platform_connected'] = $is_connected; return $settings; } ); $output = ob_get_clean(); if ( ! empty( $output ) ) { error_log( 'WP AI Workflows initialization output: ' . $output ); } } catch ( Exception $e ) { ob_end_clean(); error_log( 'WP AI Workflows initialization error: ' . $e->getMessage() ); add_action( 'admin_notices', function () use ( $e ) { echo '

' . esc_html( 'WP AI Workflows encountered an error: ' . $e->getMessage() ) . '

'; } ); } } /** * Initialize full plugin functionality */ function initialize_full_functionality( $license ) { ob_start(); try { $components = array( new WP_AI_Workflows_Workflow(), new WP_AI_Workflows_Shortcode(), new WP_AI_Workflows_Node_Execution(), new WP_AI_Workflows_Utilities(), new WP_AI_Workflows_Chat_Embedder(), new WP_AI_Workflows_Assistant_Chat(), new WP_AI_Workflows_Viewer(), new WP_AI_Workflows_Whitelabel(), new WP_AI_Workflows_Multimedia_Generator(), new WP_AI_Workflows_MCP_Client(), new WP_AI_Workflows_Chat_Preview(), new WP_AI_Workflows_Abilities(), ); foreach ( $components as $component ) { $component->init(); } // Construct the handler so its version-gated schema self-heal // (maybe_update_db_structure) runs at most once per plugin version. // The previous unconditional check_and_add_missing_columns() call ran a // SHOW COLUMNS query on every request, flooding debug.log. new WP_AI_Workflows_Human_Tasks(); new WP_AI_Workflows_Firecrawl(); new WP_AI_Workflows_Parser(); new WP_AI_Workflows_Generator(); new WP_AI_Workflows_Vector_Store(); // Phase 3 (R6.5): no license nag — the plugin is free. $license is retained // in the signature only for backward compatibility with the dormant classes. unset( $license ); $output = ob_get_clean(); if ( ! empty( $output ) ) { error_log( 'WP AI Workflows full initialization output: ' . $output ); } } catch ( Exception $e ) { ob_end_clean(); error_log( 'WP AI Workflows full initialization error: ' . $e->getMessage() ); throw $e; } } /** * Schedule daily maintenance cron job */ function wp_ai_workflows_schedule_daily_maintenance() { if ( ! wp_next_scheduled( 'wp_ai_workflows_daily_maintenance' ) ) { wp_schedule_event( time(), 'daily', 'wp_ai_workflows_daily_maintenance' ); } } add_action( 'wp', 'wp_ai_workflows_schedule_daily_maintenance' ); /** * Handle inactive license state */ function handle_inactive_license( $license ) { if ( $license->get_license_key() ) { add_action( 'admin_notices', 'wp_ai_workflows_inactive_license_notice' ); } else { add_action( 'admin_notices', 'wp_ai_workflows_no_license_notice' ); } } /** * Schedule cleanup cron job */ function wp_ai_workflows_schedule_cleanup_cron() { if ( ! wp_next_scheduled( 'wp_ai_workflows_cleanup' ) ) { wp_schedule_event( time(), 'daily', 'wp_ai_workflows_cleanup' ); } } /** * Schedule license check cron job */ function wp_ai_workflows_schedule_license_check() { if ( ! wp_next_scheduled( 'wp_ai_workflows_check_license' ) ) { wp_schedule_event( time(), 'daily', 'wp_ai_workflows_check_license' ); } } add_action( 'wp', 'wp_ai_workflows_schedule_cleanup_cron' ); add_action( 'wp', 'wp_ai_workflows_schedule_license_check' ); add_action( 'wp_ai_workflows_send_delayed_email', array( 'WP_AI_Workflows_Node_Execution', 'send_email' ), 10, 2 ); add_action( 'init', function () { WP_AI_Workflows_Chat_Embedder::get_instance()->init(); } ); add_action( 'wp_ai_workflows_cleanup_chat_data', array( 'WP_AI_Workflows_Database', 'cleanup_old_chat_data' ) ); add_action( 'wp_ai_workflows_cleanup_assistant_chat', array( 'WP_AI_Workflows_Assistant_Setup', 'cleanup_old_data' ) ); add_action( 'wp_ai_workflows_daily_maintenance', array( 'WP_AI_Workflows_Assistant_Chat', 'cleanup_old_data' ) ); add_action( 'wp_ai_workflows_daily_maintenance', function () { set_transient( 'wp_ai_workflows_maintenance_mode', true, 300 ); global $wpdb; $optimization_threshold = 10; $pattern = '^wp_ai_workflows_lic_[a-f0-9]{8}$'; $transient_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->options} WHERE option_name REGEXP %s", $pattern ) ); if ( $transient_count > $optimization_threshold ) { // Keep recent entries, remove old ones $limit_count = max( 0, intval( $transient_count ) - 5 ); $entries = $wpdb->get_col( $wpdb->prepare( "SELECT option_name FROM {$wpdb->options} WHERE option_name REGEXP %s ORDER BY option_id ASC LIMIT %d", $pattern, $limit_count ) ); foreach ( $entries as $entry ) { delete_option( $entry ); } WP_AI_Workflows_Utilities::debug_log( 'Database optimization completed', 'info', array( 'optimized_entries' => count( $entries ), ) ); } delete_transient( 'wp_ai_workflows_maintenance_mode' ); } ); /** * Plugin update check */ function wp_ai_workflows_update_check() { ob_start(); try { $current_version = get_option( 'wp_ai_workflows_pro_version', '0' ); $current_db_version = get_option( WP_AI_WORKFLOWS_DB_VERSION_OPTION, '0' ); if ( version_compare( $current_version, WP_AI_WORKFLOWS_PRO_VERSION, '<' ) ) { wp_ai_workflows_migrate_license_data(); if ( $current_version === '0' ) { activate_wp_ai_workflows(); } update_option( 'wp_ai_workflows_pro_version', WP_AI_WORKFLOWS_PRO_VERSION ); } WP_AI_Workflows_Database::update_database_schema(); $cost_settings = WP_AI_Workflows_Cost_Management::get_instance()->get_cost_settings(); if ( empty( $cost_settings ) ) { WP_AI_Workflows_Cost_Management::get_instance()->initialize_cost_settings(); } if ( version_compare( $current_db_version, WP_AI_WORKFLOWS_PRO_VERSION, '<' ) ) { update_option( WP_AI_WORKFLOWS_DB_VERSION_OPTION, WP_AI_WORKFLOWS_PRO_VERSION ); WP_AI_Workflows_Utilities::debug_log( 'Database updated', 'info', array( 'from_version' => $current_db_version, 'to_version' => WP_AI_WORKFLOWS_PRO_VERSION, ) ); } } catch ( Exception $e ) { WP_AI_Workflows_Utilities::debug_log( 'Update check failed', 'error', array( 'error' => $e->getMessage(), ) ); error_log( 'WP AI Workflows update check error: ' . $e->getMessage() ); } } add_action( 'plugins_loaded', 'wp_ai_workflows_update_check' ); /** * Check license status */ function wp_ai_workflows_check_license() { ob_start(); try { $license = new WP_AI_Workflows_License(); $license->check_license(); $output = ob_get_clean(); if ( ! empty( $output ) ) { error_log( 'WP AI Workflows license check output: ' . $output ); } } catch ( Exception $e ) { ob_end_clean(); error_log( 'WP AI Workflows license check error: ' . $e->getMessage() ); } } add_action( 'wp_ai_workflows_check_license', 'wp_ai_workflows_check_license' ); /** * License notice functions */ function wp_ai_workflows_inactive_license_notice() { ?>

activate your license to access all features.' ); ?>

Learn More' ); ?>

check_and_add_missing_columns(); $output = ob_get_clean(); if ( ! empty( $output ) ) { error_log( 'WP AI Workflows activate/update output: ' . $output ); } } catch ( Exception $e ) { ob_end_clean(); error_log( 'WP AI Workflows activate/update error: ' . $e->getMessage() ); throw $e; } } register_activation_hook( __FILE__, 'wp_ai_workflows_activate_or_update' ); add_action( 'plugins_loaded', function () { ob_start(); try { $current_version = get_option( 'wp_ai_workflows_version' ); $current_db_version = get_option( WP_AI_WORKFLOWS_DB_VERSION_OPTION ); if ( $current_version !== WP_AI_WORKFLOWS_PRO_VERSION || $current_db_version !== WP_AI_WORKFLOWS_PRO_VERSION ) { delete_option( 'wp_ai_workflows_human_tasks_db_version' ); wp_ai_workflows_activate_or_update(); update_option( 'wp_ai_workflows_version', WP_AI_WORKFLOWS_PRO_VERSION ); update_option( WP_AI_WORKFLOWS_DB_VERSION_OPTION, WP_AI_WORKFLOWS_PRO_VERSION ); WP_AI_Workflows_Utilities::debug_log( 'Plugin and database updated', 'info', array( 'old_version' => $current_version, 'old_db_version' => $current_db_version, 'new_version' => WP_AI_WORKFLOWS_PRO_VERSION, ) ); } $output = ob_get_clean(); if ( ! empty( $output ) ) { error_log( 'WP AI Workflows version check output: ' . $output ); } } catch ( Exception $e ) { ob_end_clean(); error_log( 'WP AI Workflows version check error: ' . $e->getMessage() ); } } ); /** * Initialize charset settings */ function wp_ai_workflows_init_charset() { add_filter( 'rest_pre_serve_request', function ( $served, $result ) { header( 'Content-Type: application/json; charset=utf-8' ); return $served; }, 10, 2 ); } add_action( 'init', 'wp_ai_workflows_init_charset' ); /** * Set up plugin files and directories */ function wp_ai_workflows_setup_files() { ob_start(); try { $directories = array( 'includes/prompts', 'includes/templates', ); foreach ( $directories as $dir ) { $path = WP_AI_WORKFLOWS_PLUGIN_DIR . $dir; if ( ! file_exists( $path ) ) { if ( ! mkdir( $path, 0755, true ) && ! is_dir( $path ) ) { throw new \RuntimeException( sprintf( 'Directory "%s" was not created', $path ) ); } } } $template_file = WP_AI_WORKFLOWS_PLUGIN_DIR . 'includes/templates/system_prompt.xml'; $prompt_file = WP_AI_WORKFLOWS_PLUGIN_DIR . 'includes/prompts/system_prompt.xml'; $assistant_template = WP_AI_WORKFLOWS_PLUGIN_DIR . 'includes/templates/assistant_system_prompt.xml'; $assistant_prompt = WP_AI_WORKFLOWS_PLUGIN_DIR . 'includes/prompts/assistant_system_prompt.xml'; if ( ! file_exists( $template_file ) ) { $default_template = WP_AI_WORKFLOWS_PLUGIN_DIR . 'includes/data/system_prompt.xml'; if ( ! copy( $default_template, $template_file ) ) { throw new \RuntimeException( 'Failed to copy system prompt template' ); } } if ( ! file_exists( $assistant_prompt ) && file_exists( $assistant_template ) ) { copy( $assistant_template, $assistant_prompt ); } if ( ! file_exists( $prompt_file ) ) { if ( ! copy( $template_file, $prompt_file ) ) { throw new \RuntimeException( 'Failed to copy system prompt file' ); } } $output = ob_get_clean(); if ( ! empty( $output ) ) { error_log( 'WP AI Workflows file setup output: ' . $output ); } } catch ( Exception $e ) { ob_end_clean(); error_log( 'WP AI Workflows file setup error: ' . $e->getMessage() ); throw $e; } } run_wp_ai_workflows(); restore_error_handler(); } // end COMPILE-SAFETY WRAPPER: if ( ! function_exists( 'wp_ai_workflows_handle_error' ) )