usergroup->can( 'mai' ) ) { wp_die( __( 'You do not have sufficient permissions to access this page.', 'wpforo' ) ); } // Include helper functions and tab content files FIRST (before using them) require_once __DIR__ . '/tabs/ai-features-helpers.php'; require_once __DIR__ . '/tabs/ai-features-tab-overview.php'; require_once __DIR__ . '/tabs/ai-features-tab-rag-indexing.php'; require_once __DIR__ . '/tabs/ai-features-tab-wp-indexing.php'; require_once __DIR__ . '/tabs/ai-features-tab-ai-tools.php'; require_once __DIR__ . '/tabs/ai-features-tab-ai-tasks.php'; require_once __DIR__ . '/tabs/ai-features-tab-analytics.php'; require_once __DIR__ . '/tabs/ai-features-tab-ai-logs.php'; // Determine current tab early (needed for conditional script loading) $current_tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'overview'; // Enqueue AI Features scripts and styles wp_enqueue_style( 'wpforo-ai-features', WPFORO_URL . '/admin/assets/css/ai-features.css', [], WPFORO_VERSION ); // Chart.js is only needed on the analytics tab - don't load it elsewhere $ai_features_deps = [ 'jquery', 'suggest' ]; if ( $current_tab === 'analytics' ) { wp_enqueue_script( 'wpforo-chart-js', WPFORO_URL . '/admin/assets/js/chart.min.js', [], '4.4.1', true ); $ai_features_deps[] = 'wpforo-chart-js'; } wp_enqueue_script( 'wpforo-ai-features', WPFORO_URL . '/admin/assets/js/ai-features.js', $ai_features_deps, WPFORO_VERSION, false ); // WordPress Indexing tab - load isolated scripts/styles if ( $current_tab === 'wp_indexing' ) { wp_enqueue_style( 'wpforo-ai-wp-indexing', WPFORO_URL . '/admin/assets/css/ai-features-wp-indexing.css', [ 'wpforo-ai-features' ], WPFORO_VERSION ); wp_enqueue_script( 'wpforo-ai-wp-indexing', WPFORO_URL . '/admin/assets/js/ai-features-wp-indexing.js', [ 'jquery' ], WPFORO_VERSION, true ); } // File Indexing tab - load isolated scripts/styles and media library if ( $current_tab === 'ai_tools' ) { wp_enqueue_media(); wp_enqueue_style( 'wpforo-ai-tools', WPFORO_URL . '/admin/assets/css/ai-features-tools.css', [ 'wpforo-ai-features' ], WPFORO_VERSION ); wp_enqueue_script( 'wpforo-ai-tools', WPFORO_URL . '/admin/assets/js/ai-features-tools.js', [ 'jquery', 'wpforo-ai-features' ], WPFORO_VERSION, true ); } // Localize script with AJAX URL and nonce wp_localize_script( 'wpforo-ai-features', 'wpforoAIAdmin', [ 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'wpforo_ai_features_nonce' ), 'adminNonce' => wp_create_nonce( 'wpforo_admin_ajax' ), // For WordPress content indexing AJAX calls 'debugMode' => (bool) wpforo_setting( 'general', 'debug_mode' ), 'strings' => [ 'indexing' => __( 'Indexing...', 'wpforo' ), 'idle' => __( 'Idle', 'wpforo' ), 'noActivity' => __( 'No activity yet', 'wpforo' ), ], ] ); // Localize i18n strings for AI logs (wpforoAI is used by WpForoAILogs module) wp_localize_script( 'wpforo-ai-features', 'wpforoAI', [ 'i18n' => [ 'confirmDelete' => __( 'Are you sure you want to delete this log?', 'wpforo' ), 'confirmDeleteSelected' => __( 'Are you sure you want to delete the selected logs?', 'wpforo' ), 'deleteAllLogs' => __( 'Delete All Logs', 'wpforo' ), 'noLogs' => __( 'No logs found.', 'wpforo' ), ], ] ); // Initialize AI Client if ( ! isset( WPF()->ai_client ) ) { WPF()->ai_client = new \wpforo\classes\AIClient(); } // Pricing is now static - no cache refresh needed // Handle form submissions $notice = wpforo_ai_handle_form_actions(); // Clear WordPress object cache for options (in case of external cache plugins) // This ensures fresh values from DB after form submissions wp_cache_delete( 'alloptions', 'options' ); wp_cache_delete( 'notoptions', 'options' ); // Note: Status transient is only cleared by specific actions (connect, disconnect, refresh) // NOT on every page load - the 5-minute cache in get_tenant_status() prevents excessive API calls // Get current connection status (fresh from database) // Use global options (shared across all boards) to check connection $api_key = WPF()->ai_client->get_api_key(); $tenant_id = WPF()->ai_client->get_tenant_id(); $is_connected = ! empty( $api_key ) && ! empty( $tenant_id ); // Check if returning from Freemius purchase (for status badge update) $is_post_purchase = (isset( $_GET['upgraded'] ) && $_GET['upgraded'] == '1') || (isset( $_GET['credits_purchased'] ) && $_GET['credits_purchased'] == '1'); $purchased_plan = isset( $_GET['plan'] ) ? sanitize_key( $_GET['plan'] ) : ''; // Get tenant status if connected // Force fresh fetch when returning from purchase to get updated credits $status = null; if ( $is_connected ) { $status = WPF()->ai_client->get_tenant_status( $is_post_purchase ); if ( is_wp_error( $status ) ) { // Connection exists but status fetch failed - show error state $connection_error = $status; $is_connected = false; } } // Determine current state $current_state = wpforo_ai_get_current_state( $is_connected, $status ); // If pending_approval and status is missing/error, construct from transient if ( $current_state === 'pending_approval' && ( ! $status || is_wp_error( $status ) ) ) { $pending = get_transient( 'wpforo_ai_pending_approval' ); if ( $pending ) { $status = [ 'subscription' => [ 'status' => 'pending_approval', 'plan' => 'free_trial', 'credits_total' => wpfval( $pending, 'credits_total' ) ?: 500, ], ]; } } ?>