| 1 |
<?php |
| 2 |
/** |
| 3 |
* AI Features - Overview Tab |
| 4 |
* |
| 5 |
* Overview tab content showing connection status, subscription details, and pricing |
| 6 |
* |
| 7 |
* @package wpForo |
| 8 |
* @subpackage Admin |
| 9 |
*/ |
| 10 |
|
| 11 |
if ( ! defined( 'ABSPATH' ) ) { |
| 12 |
exit; |
| 13 |
} |
| 14 |
|
| 15 |
function wpforo_ai_render_not_connected_state() { |
| 16 |
// Check if current site is localhost/development WITHOUT dev key |
| 17 |
// If WPFORO_AI_DEV_KEY is defined, allow localhost connections |
| 18 |
$is_localhost = wpforo_ai_is_localhost(); |
| 19 |
$has_dev_key = defined( 'WPFORO_AI_DEV_KEY' ) && WPFORO_AI_DEV_KEY; |
| 20 |
$block_localhost = $is_localhost && ! $has_dev_key; |
| 21 |
?> |
| 22 |
<div class="wpforo-ai-state wpforo-ai-not-connected"> |
| 23 |
|
| 24 |
<!-- Connection Status Box --> |
| 25 |
<div class="wpforo-ai-box wpforo-ai-connection-box"> |
| 26 |
<div class="wpforo-ai-box-header" style="display: flex; justify-content: space-between; align-items: center;"> |
| 27 |
<h2 style="margin: 0;"><?php _e( 'Connection Status', 'wpforo' ); ?></h2> |
| 28 |
<form method="post" action="" style="margin: 0;"> |
| 29 |
<?php wp_nonce_field( 'wpforo_ai_refresh_status' ); ?> |
| 30 |
<input type="hidden" name="wpforo_ai_action" value="refresh_status"> |
| 31 |
<button type="submit" class="button button-small" title="<?php esc_attr_e( 'Refresh Status', 'wpforo' ); ?>"> |
| 32 |
<span class="dashicons dashicons-update" style="vertical-align: middle;"></span> |
| 33 |
</button> |
| 34 |
</form> |
| 35 |
</div> |
| 36 |
<div class="wpforo-ai-box-body"> |
| 37 |
<div class="wpforo-ai-status-badge status-warning"> |
| 38 |
<span class="dashicons dashicons-warning"></span> |
| 39 |
<?php _e( 'Not Connected', 'wpforo' ); ?> |
| 40 |
</div> |
| 41 |
|
| 42 |
<p class="wpforo-ai-description" style="display: none;"> |
| 43 |
<?php _e( 'Connect your forum to wpForo AI to unlock powerful AI features including semantic search, content creation, moderation, and intelligent assistance.', 'wpforo' ); ?> |
| 44 |
</p> |
| 45 |
|
| 46 |
<div class="wpforo-ai-callout"> |
| 47 |
<strong><?php _e( 'Start with 500 FREE credits, then subscribe to an AI Plan whenever you\'re ready! Activate AI features in one click!', 'wpforo' ); ?></strong> |
| 48 |
</div> |
| 49 |
|
| 50 |
<?php if ( $block_localhost ) : ?> |
| 51 |
<div class="wpforo-ai-localhost-warning"> |
| 52 |
<span class="dashicons dashicons-warning"></span> |
| 53 |
<?php _e( 'API key generation is only available for live websites. Please deploy your site to a public domain to connect to wpForo AI.', 'wpforo' ); ?> |
| 54 |
</div> |
| 55 |
<button type="button" class="button button-primary button-hero" disabled> |
| 56 |
<span class="dashicons dashicons-admin-plugins" style="vertical-align: sub;"></span> |
| 57 |
<?php _e( 'Connect to wpForo AI Features', 'wpforo' ); ?> |
| 58 |
</button> |
| 59 |
<?php else : ?> |
| 60 |
<form method="post" action="" id="wpforo-ai-connect-form"> |
| 61 |
<?php wp_nonce_field( 'wpforo_ai_connect' ); ?> |
| 62 |
<input type="hidden" name="wpforo_ai_action" value="connect"> |
| 63 |
|
| 64 |
<!-- Terms Agreement Checkbox --> |
| 65 |
<div class="wpforo-ai-terms-agreement" style="margin-bottom: 20px; padding: 15px; background: #f8f9fa; border: 1px solid #ddd; border-radius: 4px;"> |
| 66 |
<label style="display: flex; align-items: flex-start; gap: 10px; cursor: pointer;"> |
| 67 |
<input type="checkbox" name="wpforo_ai_agree_terms" id="wpforo-ai-agree-terms" value="1" required style="margin-top: 3px;"> |
| 68 |
<span style="font-size: 13px; line-height: 1.5;"> |
| 69 |
<?php |
| 70 |
printf( |
| 71 |
__( 'I have read and agree to the %1$s and %2$s. I understand that my forum content will be processed by %3$s service as described in these documents.', 'wpforo' ), |
| 72 |
'<a href="#" class="wpforo-ai-legal-link" data-document="terms" style="text-decoration: none;">' . __( 'Terms of Service', 'wpforo' ) . '</a>', |
| 73 |
'<a href="#" class="wpforo-ai-legal-link" data-document="privacy" style="text-decoration: none;">' . __( 'Privacy Policy', 'wpforo' ) . '</a>', |
| 74 |
'<a href="https://wpforo.com/gvectors-ai/" target="_blank" style="text-decoration: none;">' . __( 'gVectors AI', 'wpforo' ) . '</a>', |
| 75 |
); |
| 76 |
?> |
| 77 |
</span> |
| 78 |
</label> |
| 79 |
</div> |
| 80 |
|
| 81 |
<button type="submit" class="button button-primary button-hero" id="wpforo-ai-connect-btn"> |
| 82 |
<span class="dashicons dashicons-admin-plugins" style="vertical-align: sub;"></span> |
| 83 |
<?php _e( 'Connect to wpForo AI Features', 'wpforo' ); ?> |
| 84 |
</button> |
| 85 |
</form> |
| 86 |
<?php endif; ?> |
| 87 |
|
| 88 |
<!-- Legal Documents Modal --> |
| 89 |
<div id="wpforo-ai-legal-modal" class="wpforo-ai-modal" style="display: none;"> |
| 90 |
<div class="wpforo-ai-modal-overlay"></div> |
| 91 |
<div class="wpforo-ai-modal-container"> |
| 92 |
<div class="wpforo-ai-modal-header"> |
| 93 |
<h2 id="wpforo-ai-modal-title"></h2> |
| 94 |
<button type="button" class="wpforo-ai-modal-close" aria-label="<?php esc_attr_e( 'Close', 'wpforo' ); ?>"> |
| 95 |
<span class="dashicons dashicons-no-alt"></span> |
| 96 |
</button> |
| 97 |
</div> |
| 98 |
<div class="wpforo-ai-modal-body" id="wpforo-ai-modal-content"> |
| 99 |
<!-- Content loaded dynamically --> |
| 100 |
</div> |
| 101 |
<div class="wpforo-ai-modal-footer"> |
| 102 |
<button type="button" class="button button-primary wpforo-ai-modal-close-btn"> |
| 103 |
<?php _e( 'Close', 'wpforo' ); ?> |
| 104 |
</button> |
| 105 |
</div> |
| 106 |
</div> |
| 107 |
</div> |
| 108 |
</div> |
| 109 |
</div> |
| 110 |
|
| 111 |
<!-- Getting Started Steps Box --> |
| 112 |
<?php wpforo_ai_render_getting_started_steps( false ); ?> |
| 113 |
|
| 114 |
<!-- Video Tutorials Box --> |
| 115 |
<?php wpforo_ai_render_video_tutorials(); ?> |
| 116 |
|
| 117 |
<!-- Features Preview Box --> |
| 118 |
<div class="wpforo-ai-box wpforo-ai-features-preview-box"> |
| 119 |
<div class="wpforo-ai-box-header"> |
| 120 |
<h2><?php _e( 'wpForo AI Features', 'wpforo' ); ?></h2> |
| 121 |
</div> |
| 122 |
<div class="wpforo-ai-box-body"> |
| 123 |
<?php wpforo_ai_render_features_preview(); ?> |
| 124 |
</div> |
| 125 |
</div> |
| 126 |
|
| 127 |
</div> |
| 128 |
<?php |
| 129 |
} |
| 130 |
|
| 131 |
/** |
| 132 |
* Render "Pending Approval" state |
| 133 |
* |
| 134 |
* Shown when tenant has registered but admin approval is required before |
| 135 |
* they can use the API. The API key is saved but API calls are blocked. |
| 136 |
* |
| 137 |
* @param array $status Tenant status data |
| 138 |
*/ |
| 139 |
function wpforo_ai_render_pending_approval_state( $status ) { |
| 140 |
$subscription = isset( $status['subscription'] ) ? $status['subscription'] : []; |
| 141 |
$credits_total = isset( $subscription['credits_total'] ) ? $subscription['credits_total'] : 500; |
| 142 |
?> |
| 143 |
<div class="wpforo-ai-state wpforo-ai-pending-approval"> |
| 144 |
|
| 145 |
<!-- Connection Status Box --> |
| 146 |
<div class="wpforo-ai-box wpforo-ai-connection-box"> |
| 147 |
<div class="wpforo-ai-box-header" style="display: flex; justify-content: space-between; align-items: center;"> |
| 148 |
<h2 style="margin: 0;"><?php _e( 'Connection Status', 'wpforo' ); ?></h2> |
| 149 |
<form method="post" action="" style="margin: 0;"> |
| 150 |
<?php wp_nonce_field( 'wpforo_ai_refresh_status' ); ?> |
| 151 |
<input type="hidden" name="wpforo_ai_action" value="refresh_status"> |
| 152 |
<button type="submit" class="button button-small" title="<?php esc_attr_e( 'Refresh Status', 'wpforo' ); ?>"> |
| 153 |
<span class="dashicons dashicons-update" style="vertical-align: middle;"></span> |
| 154 |
</button> |
| 155 |
</form> |
| 156 |
</div> |
| 157 |
<div class="wpforo-ai-box-body"> |
| 158 |
<div class="wpforo-ai-status-badge status-pending"> |
| 159 |
<span class="dashicons dashicons-clock"></span> |
| 160 |
<?php _e( 'Awaiting Activation', 'wpforo' ); ?> |
| 161 |
</div> |
| 162 |
|
| 163 |
<p class="wpforo-ai-description"> |
| 164 |
<?php _e( 'Your API key has been generated and your account is registered. An administrator will review and activate your account shortly.', 'wpforo' ); ?> |
| 165 |
</p> |
| 166 |
|
| 167 |
<div class="wpforo-ai-callout wpforo-ai-callout-info"> |
| 168 |
<span class="dashicons dashicons-info"></span> |
| 169 |
<?php |
| 170 |
printf( |
| 171 |
__( 'Once activated, you will have %s free credits to get started with AI features.', 'wpforo' ), |
| 172 |
'<strong>' . number_format( $credits_total ) . '</strong>' |
| 173 |
); |
| 174 |
?> |
| 175 |
</div> |
| 176 |
|
| 177 |
<div class="wpforo-ai-pending-actions"> |
| 178 |
<!-- Refresh Status Button --> |
| 179 |
<form method="post" action="" style="display: inline-block; margin-top: 15px;"> |
| 180 |
<?php wp_nonce_field( 'wpforo_ai_refresh_status' ); ?> |
| 181 |
<input type="hidden" name="wpforo_ai_action" value="refresh_status"> |
| 182 |
<button type="submit" class="button"> |
| 183 |
<span class="dashicons dashicons-update" style="vertical-align: middle;"></span> |
| 184 |
<?php _e( 'Check Activation Status', 'wpforo' ); ?> |
| 185 |
</button> |
| 186 |
</form> |
| 187 |
|
| 188 |
<!-- Disconnect Button --> |
| 189 |
<form method="post" action="" style="display: inline-block; margin-left: 10px;"> |
| 190 |
<?php wp_nonce_field( 'wpforo_ai_disconnect' ); ?> |
| 191 |
<input type="hidden" name="wpforo_ai_action" value="disconnect"> |
| 192 |
<button type="submit" class="button wpforo-ai-disconnect-btn"> |
| 193 |
<?php _e( 'Cancel Registration', 'wpforo' ); ?> |
| 194 |
</button> |
| 195 |
</form> |
| 196 |
</div> |
| 197 |
</div> |
| 198 |
</div> |
| 199 |
|
| 200 |
<!-- Video Tutorials Box --> |
| 201 |
<?php wpforo_ai_render_video_tutorials(); ?> |
| 202 |
|
| 203 |
<!-- Features Preview Box --> |
| 204 |
<div class="wpforo-ai-box wpforo-ai-features-preview-box"> |
| 205 |
<div class="wpforo-ai-box-header"> |
| 206 |
<h2><?php _e( 'Available After Activation', 'wpforo' ); ?></h2> |
| 207 |
</div> |
| 208 |
<div class="wpforo-ai-box-body"> |
| 209 |
<?php wpforo_ai_render_features_preview(); ?> |
| 210 |
</div> |
| 211 |
</div> |
| 212 |
|
| 213 |
</div> |
| 214 |
<?php |
| 215 |
} |
| 216 |
|
| 217 |
/** |
| 218 |
* Render "Inactive" state |
| 219 |
* |
| 220 |
* Shown when an administrator has temporarily deactivated the tenant. |
| 221 |
* API calls are blocked until the admin reactivates the account. |
| 222 |
* No connect button should be shown since the account exists. |
| 223 |
* |
| 224 |
* @param array $status Tenant status data |
| 225 |
*/ |
| 226 |
function wpforo_ai_render_inactive_state( $status ) { |
| 227 |
?> |
| 228 |
<div class="wpforo-ai-state wpforo-ai-inactive"> |
| 229 |
|
| 230 |
<!-- Connection Status Box --> |
| 231 |
<div class="wpforo-ai-box wpforo-ai-connection-box"> |
| 232 |
<div class="wpforo-ai-box-header" style="display: flex; justify-content: space-between; align-items: center;"> |
| 233 |
<h2 style="margin: 0;"><?php _e( 'Connection Status', 'wpforo' ); ?></h2> |
| 234 |
<form method="post" action="" style="margin: 0;"> |
| 235 |
<?php wp_nonce_field( 'wpforo_ai_refresh_status' ); ?> |
| 236 |
<input type="hidden" name="wpforo_ai_action" value="refresh_status"> |
| 237 |
<button type="submit" class="button button-small" title="<?php esc_attr_e( 'Refresh Status', 'wpforo' ); ?>"> |
| 238 |
<span class="dashicons dashicons-update" style="vertical-align: middle;"></span> |
| 239 |
</button> |
| 240 |
</form> |
| 241 |
</div> |
| 242 |
<div class="wpforo-ai-box-body"> |
| 243 |
<div class="wpforo-ai-status-badge status-inactive"> |
| 244 |
<span class="dashicons dashicons-marker"></span> |
| 245 |
<?php _e( 'Temporarily Inactive', 'wpforo' ); ?> |
| 246 |
</div> |
| 247 |
|
| 248 |
<p class="wpforo-ai-description"> |
| 249 |
<?php _e( 'Your wpForo AI account has been temporarily deactivated by an administrator. AI features are currently unavailable.', 'wpforo' ); ?> |
| 250 |
</p> |
| 251 |
|
| 252 |
<div class="wpforo-ai-callout wpforo-ai-callout-warning"> |
| 253 |
<span class="dashicons dashicons-info"></span> |
| 254 |
<?php |
| 255 |
printf( |
| 256 |
__( 'Please %s if you believe this is an error or if you need assistance reactivating your account.', 'wpforo' ), |
| 257 |
'<a href="https://wpforo.com/login-register/?tab=login" target="_blank">' . __( 'open a support ticket', 'wpforo' ) . '</a>' |
| 258 |
); |
| 259 |
?> |
| 260 |
</div> |
| 261 |
|
| 262 |
<div class="wpforo-ai-inactive-actions"> |
| 263 |
<!-- Refresh Status Button --> |
| 264 |
<form method="post" action="" style="display: inline-block; margin-top: 15px;"> |
| 265 |
<?php wp_nonce_field( 'wpforo_ai_refresh_status' ); ?> |
| 266 |
<input type="hidden" name="wpforo_ai_action" value="refresh_status"> |
| 267 |
<button type="submit" class="button"> |
| 268 |
<span class="dashicons dashicons-update" style="vertical-align: middle;"></span> |
| 269 |
<?php _e( 'Check Account Status', 'wpforo' ); ?> |
| 270 |
</button> |
| 271 |
</form> |
| 272 |
</div> |
| 273 |
</div> |
| 274 |
</div> |
| 275 |
|
| 276 |
<!-- Video Tutorials Box --> |
| 277 |
<?php wpforo_ai_render_video_tutorials(); ?> |
| 278 |
|
| 279 |
<!-- Features Preview Box (disabled state) --> |
| 280 |
<div class="wpforo-ai-box wpforo-ai-features-preview-box" style="opacity: 0.6;"> |
| 281 |
<div class="wpforo-ai-box-header"> |
| 282 |
<h2><?php _e( 'Features Unavailable', 'wpforo' ); ?></h2> |
| 283 |
</div> |
| 284 |
<div class="wpforo-ai-box-body"> |
| 285 |
<?php wpforo_ai_render_features_preview(); ?> |
| 286 |
</div> |
| 287 |
</div> |
| 288 |
|
| 289 |
</div> |
| 290 |
<?php |
| 291 |
} |
| 292 |
|
| 293 |
/** |
| 294 |
* Render "Free Trial" state |
| 295 |
* |
| 296 |
* @param array $status Tenant status data |
| 297 |
* @param bool $is_post_purchase Whether this is a post-purchase page load |
| 298 |
*/ |
| 299 |
function wpforo_ai_render_free_trial_state( $status, $is_post_purchase = false ) { |
| 300 |
$subscription = isset($status['subscription']) ? $status['subscription'] : []; |
| 301 |
$tenant_id = isset($status['tenant_id']) ? $status['tenant_id'] : ''; |
| 302 |
$features = isset($status['features_enabled']) ? $status['features_enabled'] : []; |
| 303 |
$usage = isset($status['usage_this_month']) ? $status['usage_this_month'] : []; |
| 304 |
|
| 305 |
$credits_total = isset($subscription['credits_total']) ? $subscription['credits_total'] : 0; |
| 306 |
$credits_remaining = isset($subscription['credits_remaining']) ? $subscription['credits_remaining'] : 0; |
| 307 |
$credits_used = isset($subscription['credits_used']) ? $subscription['credits_used'] : 0; |
| 308 |
$expires_at = isset($subscription['expires_at']) ? $subscription['expires_at'] : ''; |
| 309 |
$renews_at = isset($subscription['renews_at']) ? $subscription['renews_at'] : ''; |
| 310 |
|
| 311 |
$credits_percent = $credits_total > 0 ? round( ( $credits_remaining / $credits_total ) * 100 ) : 0; |
| 312 |
|
| 313 |
wpforo_ai_render_connected_state( $status, 'free_trial', $is_post_purchase ); |
| 314 |
} |
| 315 |
|
| 316 |
/** |
| 317 |
* Render "Paid Plan" state |
| 318 |
* |
| 319 |
* @param array $status Tenant status data |
| 320 |
* @param bool $is_post_purchase Whether this is a post-purchase page load |
| 321 |
*/ |
| 322 |
function wpforo_ai_render_paid_plan_state( $status, $is_post_purchase = false ) { |
| 323 |
wpforo_ai_render_connected_state( $status, 'paid', $is_post_purchase ); |
| 324 |
} |
| 325 |
|
| 326 |
/** |
| 327 |
* Render connected state (shared between free trial and paid) |
| 328 |
* |
| 329 |
* @param array $status Tenant status data |
| 330 |
* @param string $mode 'free_trial' or 'paid' |
| 331 |
* @param bool $is_post_purchase Whether this is a post-purchase page load |
| 332 |
*/ |
| 333 |
function wpforo_ai_render_connected_state( $status, $mode = 'free_trial', $is_post_purchase = false ) { |
| 334 |
$subscription = isset($status['subscription']) && is_array($status['subscription']) ? $status['subscription'] : []; |
| 335 |
$tenant_id = isset($status['tenant_id']) ? $status['tenant_id'] : ''; |
| 336 |
$features = isset($status['features_enabled']) && is_array($status['features_enabled']) ? $status['features_enabled'] : []; |
| 337 |
$usage = isset($status['usage_this_month']) && is_array($status['usage_this_month']) ? $status['usage_this_month'] : []; |
| 338 |
$usage_lifetime = isset($status['usage_lifetime']) && is_array($status['usage_lifetime']) ? $status['usage_lifetime'] : []; |
| 339 |
$plan = isset($subscription['plan']) ? $subscription['plan'] : 'free_trial'; |
| 340 |
|
| 341 |
$credits_total = isset($subscription['credits_total']) ? (int) $subscription['credits_total'] : 0; |
| 342 |
$credits_baseline = isset($subscription['credits_baseline']) ? (int) $subscription['credits_baseline'] : $credits_total; |
| 343 |
$credits_remaining = isset($subscription['credits_remaining']) ? (int) $subscription['credits_remaining'] : 0; |
| 344 |
$credits_used = isset($subscription['credits_used']) ? (int) $subscription['credits_used'] : 0; |
| 345 |
$max_credits = isset($subscription['max_credits']) ? (int) $subscription['max_credits'] : 0; |
| 346 |
$expires_at = isset($subscription['expires_at']) ? $subscription['expires_at'] : ''; |
| 347 |
$renews_at = isset($subscription['renews_at']) ? $subscription['renews_at'] : ''; |
| 348 |
|
| 349 |
// Payment providers: detect all providers used by this tenant |
| 350 |
// API returns payment_providers array (e.g., ["freemius", "paddle"]) and payment_provider string (most recent) |
| 351 |
$payment_providers = isset($subscription['payment_providers']) && is_array($subscription['payment_providers']) ? $subscription['payment_providers'] : []; |
| 352 |
$payment_provider = isset($subscription['payment_provider']) ? $subscription['payment_provider'] : ''; |
| 353 |
// Backwards compatibility: if API doesn't return payment_providers yet, build from single value |
| 354 |
if ( empty( $payment_providers ) && $payment_provider ) { |
| 355 |
$payment_providers = [ $payment_provider ]; |
| 356 |
} |
| 357 |
// Legacy fallback: existing Freemius subscribers may not have payment_provider set |
| 358 |
if ( empty( $payment_providers ) && $mode === 'paid' ) { |
| 359 |
$payment_providers = [ 'freemius' ]; |
| 360 |
$payment_provider = 'freemius'; |
| 361 |
} |
| 362 |
|
| 363 |
$credits_percent = $credits_baseline > 0 ? round( ( $credits_remaining / $credits_baseline ) * 100 ) : 0; |
| 364 |
$is_free_trial = ( $mode === 'free_trial' ); |
| 365 |
|
| 366 |
// Get stored API key (global option, shared across all boards) |
| 367 |
$api_key = WPF()->ai_client->get_api_key(); |
| 368 |
$api_key_masked = WPF()->ai_client->mask_api_key( WPF()->ai_client->decrypt_api_key( $api_key ) ); |
| 369 |
|
| 370 |
// Check bonus credits status |
| 371 |
$bonus_credits_status = WPF()->ai_client->get_bonus_credits_status(); |
| 372 |
$bonus_credits_claimed = ! empty( $bonus_credits_status['claimed'] ); |
| 373 |
$bonus_credits_amount = $bonus_credits_claimed ? (int) $bonus_credits_status['amount'] : 0; |
| 374 |
|
| 375 |
// Check eligibility for bonus credits (only if not claimed) |
| 376 |
$bonus_credits_eligible = false; |
| 377 |
if ( ! $bonus_credits_claimed ) { |
| 378 |
$eligibility = WPF()->ai_client->check_bonus_credits_eligibility(); |
| 379 |
$bonus_credits_eligible = $eligibility['eligible']; |
| 380 |
} |
| 381 |
|
| 382 |
?> |
| 383 |
<div class="wpforo-ai-state wpforo-ai-connected <?php echo $is_free_trial ? 'wpforo-ai-free-trial' : 'wpforo-ai-paid-plan'; ?>"> |
| 384 |
|
| 385 |
<!-- Connection Status Box --> |
| 386 |
<div class="wpforo-ai-box wpforo-ai-connection-box"> |
| 387 |
<div class="wpforo-ai-box-header"> |
| 388 |
<h2><?php _e( 'Connection Status', 'wpforo' ); ?></h2> |
| 389 |
<form method="post" action="" class="wpforo-ai-refresh-form"> |
| 390 |
<?php wp_nonce_field( 'wpforo_ai_refresh_status' ); ?> |
| 391 |
<input type="hidden" name="wpforo_ai_action" value="refresh_status"> |
| 392 |
<button type="submit" class="button button-small" title="<?php esc_attr_e( 'Refresh Status', 'wpforo' ); ?>"> |
| 393 |
<span class="dashicons dashicons-update"></span> |
| 394 |
<?php _e( 'Refresh', 'wpforo' ); ?> |
| 395 |
</button> |
| 396 |
</form> |
| 397 |
</div> |
| 398 |
<div class="wpforo-ai-box-body"> |
| 399 |
<div class="wpforo-ai-status-badge status-success"> |
| 400 |
<?php if ( $is_post_purchase ) : ?> |
| 401 |
<span class="dashicons dashicons-update dashicons-spin"></span> |
| 402 |
<?php _e( 'Subscription plan is being updated...', 'wpforo' ); ?> |
| 403 |
<?php else : ?> |
| 404 |
<span class="dashicons dashicons-yes-alt"></span> |
| 405 |
<?php |
| 406 |
if ( $is_free_trial ) { |
| 407 |
_e( 'Connected (Free Trial)', 'wpforo' ); |
| 408 |
} else { |
| 409 |
printf( __( 'Connected (%s Plan)', 'wpforo' ), esc_html( ucfirst( $plan ) ) ); |
| 410 |
} |
| 411 |
?> |
| 412 |
<?php endif; ?> |
| 413 |
</div> |
| 414 |
|
| 415 |
<div class="wpforo-ai-connection-details"> |
| 416 |
<div class="detail-row"> |
| 417 |
<span class="detail-label"><?php _e( 'Tenant ID:', 'wpforo' ); ?></span> |
| 418 |
<code class="detail-value"><?php echo esc_html( $tenant_id ); ?></code> |
| 419 |
</div> |
| 420 |
<div class="detail-row"> |
| 421 |
<span class="detail-label"><?php _e( 'API Key:', 'wpforo' ); ?></span> |
| 422 |
<code class="detail-value wpforo-ai-key-masked" data-key-full="hidden"><?php echo esc_html( $api_key_masked ); ?></code> |
| 423 |
</div> |
| 424 |
|
| 425 |
<!-- License Activation Section (Freemius only) --> |
| 426 |
<?php if ( in_array( 'freemius', $payment_providers, true ) ) : ?> |
| 427 |
<div class="detail-row wpforo-ai-license-activation" style="flex-direction: column; align-items: flex-start;"> |
| 428 |
<a href="#" class="wpforo-ai-license-toggle" onclick="jQuery('.wpforo-ai-license-fields').slideToggle(200); jQuery(this).find('.dashicons').toggleClass('dashicons-arrow-right-alt2 dashicons-arrow-down-alt2'); return false;" style="text-decoration: none; color: #666; font-size: 13px;"> |
| 429 |
<span class="dashicons dashicons-arrow-right-alt2" style="vertical-align: middle; font-size: 16px; width: 16px; height: 16px;"></span> |
| 430 |
<?php _e( 'Activate by License ID (Freemius payment only)', 'wpforo' ); ?> |
| 431 |
</a> |
| 432 |
<div class="wpforo-ai-license-fields" style="display: none; margin-top: 10px;"> |
| 433 |
<div class="license-input-wrapper"> |
| 434 |
<input type="text" |
| 435 |
id="wpforo-ai-license-id" |
| 436 |
class="regular-text" |
| 437 |
placeholder="<?php esc_attr_e( 'Enter License ID from purchase email', 'wpforo' ); ?>" |
| 438 |
style="width: 250px; margin-right: 10px; inherit; font-size: 14px;" |
| 439 |
> |
| 440 |
<button type="button" class="button button-secondary wpforo-ai-activate-license-btn"> |
| 441 |
<span class="dashicons dashicons-yes-alt" style="vertical-align: middle; font-size: 18px; line-height: 16px;"></span> |
| 442 |
<?php _e( 'Activate License', 'wpforo' ); ?> |
| 443 |
</button> |
| 444 |
<span class="spinner" style="float: none; margin-top: 0;"></span> |
| 445 |
</div> |
| 446 |
<p class="description" style="margin-top: 5px; color: #111;"> |
| 447 |
<?php _e( 'If your Freemius plan was not activated automatically after purchase, enter your License ID here.', 'wpforo' ); ?> |
| 448 |
<br> |
| 449 |
<?php _e( 'You can find your License ID in the purchase confirmation email from Freemius.', 'wpforo' ); ?> |
| 450 |
</p> |
| 451 |
<div class="wpforo-ai-license-result" style="display: none; margin-top: 10px; min-width: 220px;"></div> |
| 452 |
</div> |
| 453 |
</div> |
| 454 |
<?php endif; ?> |
| 455 |
|
| 456 |
<!-- Paddle Transaction Activation Section (Paddle only) --> |
| 457 |
<?php if ( in_array( 'paddle', $payment_providers, true ) ) : ?> |
| 458 |
<div class="detail-row wpforo-ai-paddle-activation" style="flex-direction: column; align-items: flex-start;"> |
| 459 |
<a href="#" class="wpforo-ai-paddle-toggle" onclick="jQuery('.wpforo-ai-paddle-fields').slideToggle(200); jQuery(this).find('.dashicons').toggleClass('dashicons-arrow-right-alt2 dashicons-arrow-down-alt2'); return false;" style="text-decoration: none; color: #666; font-size: 13px;"> |
| 460 |
<span class="dashicons dashicons-arrow-right-alt2" style="vertical-align: middle; font-size: 16px; width: 16px; height: 16px;"></span> |
| 461 |
<?php _e( 'Activate by Transaction ID (Paddle payment only)', 'wpforo' ); ?> |
| 462 |
</a> |
| 463 |
<div class="wpforo-ai-paddle-fields" style="display: none; margin-top: 10px;"> |
| 464 |
<div class="license-input-wrapper"> |
| 465 |
<input type="text" |
| 466 |
id="wpforo-ai-paddle-txn-id" |
| 467 |
class="regular-text" |
| 468 |
placeholder="<?php esc_attr_e( 'e.g. txn_ . . . . ', 'wpforo' ); ?>" |
| 469 |
style="width: 300px; margin-right: 10px; font-size: 14px;" |
| 470 |
> |
| 471 |
<button type="button" class="button button-secondary wpforo-ai-activate-paddle-txn-btn"> |
| 472 |
<span class="dashicons dashicons-yes-alt" style="vertical-align: middle; font-size: 18px; line-height: 16px;"></span> |
| 473 |
<?php _e( 'Activate Transaction', 'wpforo' ); ?> |
| 474 |
</button> |
| 475 |
<span class="spinner" style="float: none; margin-top: 0;"></span> |
| 476 |
</div> |
| 477 |
<p class="description" style="margin-top: 5px; color: #111;"> |
| 478 |
<?php _e( 'If your Paddle payment was not registered automatically, enter your Transaction ID here.', 'wpforo' ); ?> |
| 479 |
<br> |
| 480 |
<?php _e( 'You can find the Transaction ID in invoice file of the payment confirmation email from Paddle.', 'wpforo' ); ?> |
| 481 |
</p> |
| 482 |
<div class="wpforo-ai-paddle-result" style="display: none; margin-top: 10px; min-width: 220px;"></div> |
| 483 |
</div> |
| 484 |
</div> |
| 485 |
<?php endif; ?> |
| 486 |
|
| 487 |
<div class="detail-row wpforo-ai-key-actions"> |
| 488 |
<?php if ( $bonus_credits_claimed ) : ?> |
| 489 |
<!-- Bonus Credits Already Claimed --> |
| 490 |
<span class="detail-label"><?php _e( 'Bonus Credits:', 'wpforo' ); ?></span> |
| 491 |
<button type="button" class="button wpforo-ai-bonus-credits-btn claimed" disabled> |
| 492 |
<span class="dashicons dashicons-awards"></span> |
| 493 |
<?php printf( __( 'Granted Extra Free Credits %s', 'wpforo' ), number_format( $bonus_credits_amount ) ); ?> |
| 494 |
</button> |
| 495 |
<?php elseif ( $bonus_credits_eligible ) : ?> |
| 496 |
<!-- Request Bonus Credits Button --> |
| 497 |
<span class="detail-label"><?php _e( 'Bonus Credits:', 'wpforo' ); ?></span> |
| 498 |
<button type="button" class="button wpforo-ai-bonus-credits-btn eligible"> |
| 499 |
<span class="dashicons dashicons-star-filled"></span> |
| 500 |
<?php _e( 'Request Free Credits for Forum Content Indexing', 'wpforo' ); ?> |
| 501 |
</button> |
| 502 |
<span class="spinner wpforo-ai-bonus-spinner" style="float: none; margin-top: 0;"></span> |
| 503 |
<?php endif; ?> |
| 504 |
<!-- Disconnect Service --> |
| 505 |
<button type="button" class="button button-secondary wpforo-ai-disconnect-btn"> |
| 506 |
<span class="dashicons dashicons-dismiss"></span> |
| 507 |
<?php _e( 'Disconnect Service', 'wpforo' ); ?> |
| 508 |
</button> |
| 509 |
<!-- Disconnect and Remove All Data --> |
| 510 |
<button type="button" class="button button-secondary wpforo-ai-disconnect-purge-btn" style="color: #b32d2e; border-color: #b32d2e;"> |
| 511 |
<span class="dashicons dashicons-trash"></span> |
| 512 |
<?php _e( 'Disconnect and Remove All Data', 'wpforo' ); ?> |
| 513 |
</button> |
| 514 |
</div> |
| 515 |
</div> |
| 516 |
|
| 517 |
<!-- Credits Display --> |
| 518 |
<div class="wpforo-ai-credits-section"> |
| 519 |
<div class="credits-header"> |
| 520 |
<h3><?php _e( 'AI Credits', 'wpforo' ); ?></h3> |
| 521 |
<div class="credits-numbers"> |
| 522 |
<strong><?php echo number_format( $credits_remaining ); ?></strong> |
| 523 |
<span>/</span> |
| 524 |
<span><?php echo number_format( $credits_baseline ); ?></span> |
| 525 |
<span class="credits-label"><?php _e( 'remaining', 'wpforo' ); ?></span> |
| 526 |
</div> |
| 527 |
</div> |
| 528 |
<div class="credits-progress-bar"> |
| 529 |
<div class="credits-progress-fill <?php echo wpforo_ai_get_credit_status_class( $credits_percent ); ?>" style="width: <?php echo esc_attr( $credits_percent ); ?>%;"></div> |
| 530 |
</div> |
| 531 |
<div class="credits-info"> |
| 532 |
<?php |
| 533 |
if ( $is_free_trial && ! empty( $expires_at ) ) { |
| 534 |
printf( |
| 535 |
__( 'Trial expires: %s', 'wpforo' ), |
| 536 |
'<strong>' . esc_html( wpforo_ai_format_date( $expires_at ) ) . '</strong>' |
| 537 |
); |
| 538 |
} elseif ( ! empty( $renews_at ) ) { |
| 539 |
printf( |
| 540 |
__( 'Next billing: %s', 'wpforo' ), |
| 541 |
'<strong>' . esc_html( wpforo_ai_format_date( $renews_at ) ) . '</strong>' |
| 542 |
); |
| 543 |
} |
| 544 |
?> |
| 545 |
</div> |
| 546 |
</div> |
| 547 |
<?php if ( $max_credits > 0 && ! $is_free_trial ) : ?> |
| 548 |
<div class="credits-cap-info" style="margin-top: 5px; font-size: 12px; color: #666; text-align: right;"> |
| 549 |
<span class="dashicons dashicons-info-outline" style="font-size: 14px; width: 14px; height: 14px; vertical-align: text-top;"></span> |
| 550 |
<?php printf( |
| 551 |
__( 'Maximum credit accumulation (one year of subscription plan credits): %s', 'wpforo' ), |
| 552 |
'<strong>' . number_format( $max_credits ) . '</strong>' |
| 553 |
); ?> |
| 554 |
</div> |
| 555 |
<?php endif; ?> |
| 556 |
|
| 557 |
<!-- Warning for Free Trial --> |
| 558 |
<?php if ( $is_free_trial ) : ?> |
| 559 |
<div class="wpforo-ai-warning-box"> |
| 560 |
<span class="dashicons dashicons-warning"></span> |
| 561 |
<p> |
| 562 |
<?php |
| 563 |
printf( |
| 564 |
__( 'You\'re on Free Trial. Expires on %s. Upgrade to continue using all AI features!', 'wpforo' ), |
| 565 |
esc_html( wpforo_ai_format_date( $expires_at ) ) |
| 566 |
); |
| 567 |
?> |
| 568 |
</p> |
| 569 |
</div> |
| 570 |
<?php else : ?> |
| 571 |
<div class="wpforo-ai-success-box" style="display: none;"> |
| 572 |
<span class="dashicons dashicons-yes-alt"></span> |
| 573 |
<p><?php printf( __( 'All features of %s plan are unlocked!', 'wpforo' ), $plan); ?></p> |
| 574 |
</div> |
| 575 |
<?php endif; ?> |
| 576 |
|
| 577 |
<?php if ( ! $is_free_trial && ! empty( $payment_providers ) ) : ?> |
| 578 |
<div class="wpforo-ai-payment-provider" style="margin-top: 8px; font-size: 13px; color: #555;"> |
| 579 |
<span class="dashicons dashicons-money-alt" style="font-size: 16px; width: 16px; height: 16px; vertical-align: text-bottom;"></span> |
| 580 |
<?php |
| 581 |
$provider_labels = array_map( function( $p ) { return '<strong>' . esc_html( ucfirst( $p ) ) . '</strong>'; }, $payment_providers ); |
| 582 |
printf( __( 'Payment: %s', 'wpforo' ), implode( ' + ', $provider_labels ) ); |
| 583 |
?> |
| 584 |
</div> |
| 585 |
<?php endif; ?> |
| 586 |
|
| 587 |
<!-- Action Buttons --> |
| 588 |
<div class="wpforo-ai-actions"> |
| 589 |
<?php if ( $is_free_trial ) : ?> |
| 590 |
<button type="button" class="button button-primary button-large" onclick="document.getElementById('wpforo-ai-plans').scrollIntoView({ behavior: 'smooth' })"> |
| 591 |
<span class="dashicons dashicons-cart"></span> |
| 592 |
<?php _e( 'Upgrade Now / View Subscription Plans', 'wpforo' ); ?> |
| 593 |
</button> |
| 594 |
<?php else : ?> |
| 595 |
<?php foreach ( $payment_providers as $provider ) : ?> |
| 596 |
<a href="<?php echo esc_url( wpforo_ai_get_manage_subscription_url( $provider ) ); ?>" class="button button-secondary wpf-manage-subscription wpf-provider-<?php echo esc_attr( $provider ); ?>" target="_blank"> |
| 597 |
<span class="dashicons dashicons-admin-generic"></span> |
| 598 |
<?php printf( __( 'Manage Subscription (%s)', 'wpforo' ), esc_html( ucfirst( $provider ) ) ); ?> |
| 599 |
</a> |
| 600 |
<?php endforeach; ?> |
| 601 |
<?php if ( $plan === 'starter' || $plan === 'professional' ) : ?> |
| 602 |
<button type="button" class="button button-secondary wpforo-ai-upgrade-btn" data-plan="business" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 603 |
<span class="dashicons dashicons-cart"></span> |
| 604 |
<?php _e( 'Upgrade to Business', 'wpforo' ); ?> |
| 605 |
</button> |
| 606 |
<?php endif; ?> |
| 607 |
<?php endif; ?> |
| 608 |
</div> |
| 609 |
</div> |
| 610 |
</div> |
| 611 |
|
| 612 |
<!-- Getting Started Steps Box --> |
| 613 |
<?php wpforo_ai_render_getting_started_steps(); ?> |
| 614 |
|
| 615 |
<!-- Video Tutorials Box --> |
| 616 |
<?php wpforo_ai_render_video_tutorials(); ?> |
| 617 |
|
| 618 |
<!-- Available Features Box --> |
| 619 |
<div class="wpforo-ai-box wpforo-ai-features-box"> |
| 620 |
<div class="wpforo-ai-box-header"> |
| 621 |
<h2><?php echo $is_free_trial ? __( 'Available AI Features', 'wpforo' ) : __( 'Active AI Features', 'wpforo' ); ?></h2> |
| 622 |
</div> |
| 623 |
<div class="wpforo-ai-box-body"> |
| 624 |
<?php wpforo_ai_render_features_list( $features, $usage, $is_free_trial, $status ); ?> |
| 625 |
</div> |
| 626 |
</div> |
| 627 |
|
| 628 |
<!-- Pricing Plans Box --> |
| 629 |
<div id="wpforo-ai-plans" class="wpforo-ai-box wpforo-ai-upgrade-box"> |
| 630 |
<div class="wpforo-ai-box-header"> |
| 631 |
<h2><?php echo $is_free_trial ? __( 'Upgrade Your Plan', 'wpforo' ) : __( 'Subscription Plans', 'wpforo' ); ?></h2> |
| 632 |
</div> |
| 633 |
<div class="wpforo-ai-box-body"> |
| 634 |
<?php wpforo_ai_render_pricing_table( $tenant_id, $subscription ); ?> |
| 635 |
</div> |
| 636 |
</div> |
| 637 |
|
| 638 |
<!-- Credit Packs Box (for paid users only) --> |
| 639 |
<?php if ( ! $is_free_trial ) : ?> |
| 640 |
<div class="wpforo-ai-box wpforo-ai-credit-packs-box"> |
| 641 |
<div class="wpforo-ai-box-header"> |
| 642 |
<h2><?php _e( 'Buy Additional Credits', 'wpforo' ); ?></h2> |
| 643 |
</div> |
| 644 |
<div class="wpforo-ai-box-body"> |
| 645 |
<?php wpforo_ai_render_credit_packs( $tenant_id ); ?> |
| 646 |
</div> |
| 647 |
</div> |
| 648 |
<?php endif; ?> |
| 649 |
|
| 650 |
<!-- Usage Statistics Box --> |
| 651 |
<div class="wpforo-ai-box wpforo-ai-usage-box"> |
| 652 |
<div class="wpforo-ai-box-header"> |
| 653 |
<h2><?php _e( 'Usage Statistics', 'wpforo' ); ?></h2> |
| 654 |
</div> |
| 655 |
<div class="wpforo-ai-box-body"> |
| 656 |
<?php wpforo_ai_render_usage_stats( $usage, $credits_used, $usage_lifetime, $plan ); ?> |
| 657 |
</div> |
| 658 |
</div> |
| 659 |
|
| 660 |
<!-- Account Information Box --> |
| 661 |
<div class="wpforo-ai-box wpforo-ai-advanced-box"> |
| 662 |
<div class="wpforo-ai-box-header"> |
| 663 |
<h2><?php _e( 'Account Information', 'wpforo' ); ?></h2> |
| 664 |
</div> |
| 665 |
<div class="wpforo-ai-box-body"> |
| 666 |
<div class="wpforo-ai-advanced-info"> |
| 667 |
<div class="info-row"> |
| 668 |
<span class="info-label"><?php _e( 'Forum URL:', 'wpforo' ); ?></span> |
| 669 |
<span class="info-value"><?php echo esc_html( get_site_url() ); ?></span> |
| 670 |
</div> |
| 671 |
<div class="info-row"> |
| 672 |
<span class="info-label"><?php _e( 'Admin Email:', 'wpforo' ); ?></span> |
| 673 |
<span class="info-value"><?php echo esc_html( get_option( 'admin_email' ) ); ?></span> |
| 674 |
</div> |
| 675 |
<div class="info-row"> |
| 676 |
<span class="info-label"><?php _e( 'Tenant ID:', 'wpforo' ); ?></span> |
| 677 |
<code class="info-value"><?php echo esc_html( $tenant_id ); ?></code> |
| 678 |
</div> |
| 679 |
</div> |
| 680 |
</div> |
| 681 |
</div> |
| 682 |
|
| 683 |
</div> |
| 684 |
|
| 685 |
<!-- Hidden Forms (triggered by buttons) --> |
| 686 |
<div id="wpforo-ai-hidden-forms" style="display:none;"> |
| 687 |
<!-- Disconnect Form --> |
| 688 |
<form id="wpforo-ai-disconnect-form" method="post" action=""> |
| 689 |
<?php wp_nonce_field( 'wpforo_ai_disconnect' ); ?> |
| 690 |
<input type="hidden" name="wpforo_ai_action" value="disconnect"> |
| 691 |
<div class="wpforo-ai-disconnect-warning"> |
| 692 |
<span class="dashicons dashicons-warning"></span> |
| 693 |
<p><strong><?php _e( 'Warning: This will disconnect your forum from wpForo AI service.', 'wpforo' ); ?></strong></p> |
| 694 |
<p><?php _e( 'Your credits will be preserved and restored when you reconnect. Your indexed content will be deleted after 30 days. You can reconnect anytime with the same site URL.', 'wpforo' ); ?></p> |
| 695 |
</div> |
| 696 |
<p> |
| 697 |
<label> |
| 698 |
<input type="checkbox" name="confirm" value="1" required> |
| 699 |
<?php _e( 'I understand and want to disconnect the service', 'wpforo' ); ?> |
| 700 |
</label> |
| 701 |
</p> |
| 702 |
<p> |
| 703 |
<label for="disconnect-reason"><?php _e( 'Reason (optional):', 'wpforo' ); ?></label> |
| 704 |
<textarea id="disconnect-reason" name="reason" rows="3" class="large-text" placeholder="<?php esc_attr_e( 'Help us improve by telling us why you\'re disconnecting', 'wpforo' ); ?>"></textarea> |
| 705 |
</p> |
| 706 |
</form> |
| 707 |
|
| 708 |
<!-- Disconnect and Remove All Data Form --> |
| 709 |
<form id="wpforo-ai-disconnect-purge-form" method="post" action=""> |
| 710 |
<?php wp_nonce_field( 'wpforo_ai_disconnect' ); ?> |
| 711 |
<input type="hidden" name="wpforo_ai_action" value="disconnect"> |
| 712 |
<input type="hidden" name="purge_data" value="1"> |
| 713 |
<div class="wpforo-ai-disconnect-warning" style="border-left-color: #b32d2e;"> |
| 714 |
<span class="dashicons dashicons-warning" style="color: #b32d2e;"></span> |
| 715 |
<p><strong style="color: #b32d2e;"><?php _e( 'Warning: This will permanently delete ALL your data from gVectors AI servers.', 'wpforo' ); ?></strong></p> |
| 716 |
<p><?php _e( 'This action will disconnect your forum and immediately delete all indexed content, embeddings, and tenant data from the AI service. This cannot be undone. Your credits will NOT be preserved.', 'wpforo' ); ?></p> |
| 717 |
</div> |
| 718 |
<p> |
| 719 |
<label> |
| 720 |
<input type="checkbox" name="confirm" value="1" required> |
| 721 |
<?php _e( 'I understand that all my data will be permanently deleted and want to proceed', 'wpforo' ); ?> |
| 722 |
</label> |
| 723 |
</p> |
| 724 |
<p> |
| 725 |
<label for="disconnect-purge-reason"><?php _e( 'Reason (optional):', 'wpforo' ); ?></label> |
| 726 |
<textarea id="disconnect-purge-reason" name="reason" rows="3" class="large-text" placeholder="<?php esc_attr_e( 'Help us improve by telling us why you\'re removing your data', 'wpforo' ); ?>"></textarea> |
| 727 |
</p> |
| 728 |
</form> |
| 729 |
</div> |
| 730 |
<?php |
| 731 |
} |
| 732 |
|
| 733 |
/** |
| 734 |
* Render expired subscription state |
| 735 |
* |
| 736 |
* @param array $status Tenant status data with expired subscription |
| 737 |
*/ |
| 738 |
function wpforo_ai_render_expired_state( $status ) { |
| 739 |
$tenant_id = wpfval( $status, 'tenant_id' ) ?: WPF()->ai_client->get_tenant_id(); |
| 740 |
$subscription = wpfval( $status, 'subscription' ); |
| 741 |
$expires_at = wpfval( $subscription, 'expires_at' ); |
| 742 |
$plan = wpfval( $subscription, 'plan' ); |
| 743 |
$is_trial = ( $plan === 'free_trial' ); |
| 744 |
|
| 745 |
?> |
| 746 |
<div class="wpforo-ai-state wpforo-ai-expired-state"> |
| 747 |
<div class="wpforo-ai-box wpforo-ai-error-box" style="border-left: 4px solid #d63638;"> |
| 748 |
<div class="wpforo-ai-box-header"> |
| 749 |
<h2><?php _e( 'Subscription Status', 'wpforo' ); ?></h2> |
| 750 |
</div> |
| 751 |
<div class="wpforo-ai-box-body"> |
| 752 |
<div class="wpforo-ai-status-badge status-error"> |
| 753 |
<span class="dashicons dashicons-warning"></span> |
| 754 |
<?php echo $is_trial ? __( 'Trial Expired', 'wpforo' ) : __( 'Subscription Expired', 'wpforo' ); ?> |
| 755 |
</div> |
| 756 |
|
| 757 |
<div class="wpforo-ai-error-message" style="margin: 20px 0;"> |
| 758 |
<?php if ( $is_trial ) : ?> |
| 759 |
<p><strong><?php _e( 'Your free trial has expired.', 'wpforo' ); ?></strong></p> |
| 760 |
<p><?php _e( 'To continue using AI features, please upgrade to a paid plan.', 'wpforo' ); ?></p> |
| 761 |
<?php else : ?> |
| 762 |
<p><strong><?php _e( 'Your subscription has expired.', 'wpforo' ); ?></strong></p> |
| 763 |
<p><?php _e( 'Please renew your subscription to continue using AI features.', 'wpforo' ); ?></p> |
| 764 |
<?php endif; ?> |
| 765 |
|
| 766 |
<?php if ( ! empty( $expires_at ) ) : ?> |
| 767 |
<p class="wpforo-ai-expiry-date" style="color: #666; font-size: 13px;"> |
| 768 |
<?php |
| 769 |
printf( |
| 770 |
__( 'Expired on: %s', 'wpforo' ), |
| 771 |
'<strong>' . esc_html( wpforo_ai_format_date( $expires_at ) ) . '</strong>' |
| 772 |
); |
| 773 |
?> |
| 774 |
</p> |
| 775 |
<?php endif; ?> |
| 776 |
</div> |
| 777 |
|
| 778 |
<div class="wpforo-ai-error-actions"> |
| 779 |
<button type="button" class="button button-primary button-large" onclick="document.getElementById('wpforo-ai-plans').scrollIntoView({ behavior: 'smooth' })"> |
| 780 |
<span class="dashicons dashicons-cart"></span> |
| 781 |
<?php _e( 'Upgrade Now / View Subscription Plans', 'wpforo' ); ?> |
| 782 |
</button> |
| 783 |
|
| 784 |
<form method="post" action="" style="display: inline;"> |
| 785 |
<?php wp_nonce_field( 'wpforo_ai_refresh_status' ); ?> |
| 786 |
<input type="hidden" name="wpforo_ai_action" value="refresh_status"> |
| 787 |
<button type="submit" class="button button-secondary"> |
| 788 |
<span class="dashicons dashicons-update"></span> |
| 789 |
<?php _e( 'Check Status', 'wpforo' ); ?> |
| 790 |
</button> |
| 791 |
</form> |
| 792 |
</div> |
| 793 |
|
| 794 |
<div class="wpforo-ai-support-info" style="margin-top: 20px;"> |
| 795 |
<p style="color: #666; font-size: 13px;"> |
| 796 |
<?php |
| 797 |
printf( |
| 798 |
__( 'Need help? %s', 'wpforo' ), |
| 799 |
'<a href="https://wpforo.com/login-register/?tab=login" target="_blank">' . __( 'Open Support Ticket', 'wpforo' ) . '</a>' |
| 800 |
); |
| 801 |
?> |
| 802 |
</p> |
| 803 |
</div> |
| 804 |
</div> |
| 805 |
</div> |
| 806 |
|
| 807 |
<!-- Video Tutorials Box --> |
| 808 |
<?php wpforo_ai_render_video_tutorials(); ?> |
| 809 |
|
| 810 |
<!-- Plans Section for expired users --> |
| 811 |
<div id="wpforo-ai-plans" class="wpforo-ai-box" style="margin-top: 20px;"> |
| 812 |
<div class="wpforo-ai-box-header"> |
| 813 |
<h2><?php _e( 'Available Plans', 'wpforo' ); ?></h2> |
| 814 |
</div> |
| 815 |
<div class="wpforo-ai-box-body"> |
| 816 |
<?php wpforo_ai_render_pricing_table( 'free_trial' ); ?> |
| 817 |
</div> |
| 818 |
</div> |
| 819 |
</div> |
| 820 |
<?php |
| 821 |
} |
| 822 |
|
| 823 |
/** |
| 824 |
* Render cancelled/refunded subscription state |
| 825 |
* |
| 826 |
* Shown when Freemius or Paddle webhook sets subscription_status to |
| 827 |
* "cancelled" or "refunded". The user needs a clear explanation and |
| 828 |
* actionable options: buy a new plan, disconnect, or check status. |
| 829 |
* |
| 830 |
* @param array $status Tenant status data from /tenant/status API |
| 831 |
*/ |
| 832 |
function wpforo_ai_render_cancelled_state( $status ) { |
| 833 |
$subscription = wpfval( $status, 'subscription' ); |
| 834 |
$sub_status = wpfval( $subscription, 'status' ); |
| 835 |
$is_refunded = ( $sub_status === 'refunded' ); |
| 836 |
$tenant_id = wpfval( $status, 'tenant_id' ) ?: WPF()->ai_client->get_tenant_id(); |
| 837 |
|
| 838 |
$provider = wpfval( $subscription, 'payment_provider' ); |
| 839 |
if ( empty( $provider ) ) { |
| 840 |
$provider = get_option( 'wpforo_ai_payment_provider', 'freemius' ); |
| 841 |
} |
| 842 |
|
| 843 |
?> |
| 844 |
<div class="wpforo-ai-state wpforo-ai-cancelled-state"> |
| 845 |
<div class="wpforo-ai-box wpforo-ai-error-box" style="border-left: 4px solid #d63638;"> |
| 846 |
<div class="wpforo-ai-box-header"> |
| 847 |
<h2><?php _e( 'Subscription Status', 'wpforo' ); ?></h2> |
| 848 |
</div> |
| 849 |
<div class="wpforo-ai-box-body"> |
| 850 |
<div class="wpforo-ai-status-badge status-error"> |
| 851 |
<span class="dashicons dashicons-warning"></span> |
| 852 |
<?php echo $is_refunded ? __( 'Subscription Refunded', 'wpforo' ) : __( 'Subscription Cancelled', 'wpforo' ); ?> |
| 853 |
</div> |
| 854 |
|
| 855 |
<div class="wpforo-ai-error-message" style="margin: 20px 0;"> |
| 856 |
<?php if ( $is_refunded ) : ?> |
| 857 |
<p><strong><?php _e( 'Your subscription has been refunded.', 'wpforo' ); ?></strong></p> |
| 858 |
<p><?php _e( 'AI features are currently disabled. You can purchase a new plan to reactivate the service, or disconnect to start fresh.', 'wpforo' ); ?></p> |
| 859 |
<?php else : ?> |
| 860 |
<p><strong><?php _e( 'Your subscription has been cancelled.', 'wpforo' ); ?></strong></p> |
| 861 |
<p><?php _e( 'AI features are currently disabled. You can purchase a new plan to reactivate the service, or disconnect to start fresh.', 'wpforo' ); ?></p> |
| 862 |
<?php endif; ?> |
| 863 |
|
| 864 |
<p style="color: #666; font-size: 13px;"> |
| 865 |
<?php _e( 'Your indexed content is still preserved. If you purchase a new plan, your data will be restored automatically.', 'wpforo' ); ?> |
| 866 |
</p> |
| 867 |
</div> |
| 868 |
|
| 869 |
<div class="wpforo-ai-error-actions"> |
| 870 |
<button type="button" class="button button-primary button-large" onclick="document.getElementById('wpforo-ai-plans').scrollIntoView({ behavior: 'smooth' })"> |
| 871 |
<span class="dashicons dashicons-cart"></span> |
| 872 |
<?php _e( 'Purchase New Plan', 'wpforo' ); ?> |
| 873 |
</button> |
| 874 |
|
| 875 |
<form method="post" action="" style="display: inline;"> |
| 876 |
<?php wp_nonce_field( 'wpforo_ai_refresh_status' ); ?> |
| 877 |
<input type="hidden" name="wpforo_ai_action" value="refresh_status"> |
| 878 |
<button type="submit" class="button button-secondary"> |
| 879 |
<span class="dashicons dashicons-update"></span> |
| 880 |
<?php _e( 'Check Status', 'wpforo' ); ?> |
| 881 |
</button> |
| 882 |
</form> |
| 883 |
|
| 884 |
<a href="<?php echo esc_url( wpforo_ai_get_manage_subscription_url( $provider ) ); ?>" class="button button-secondary" target="_blank"> |
| 885 |
<span class="dashicons dashicons-admin-generic"></span> |
| 886 |
<?php printf( __( 'Manage Subscription (%s)', 'wpforo' ), esc_html( ucfirst( $provider ) ) ); ?> |
| 887 |
</a> |
| 888 |
</div> |
| 889 |
|
| 890 |
<!-- Disconnect options --> |
| 891 |
<div style="margin-top: 25px; padding-top: 20px; border-top: 1px solid #e0e0e0;"> |
| 892 |
<p style="color: #666; font-size: 13px; margin-bottom: 10px;"> |
| 893 |
<?php _e( 'Want to start fresh? Disconnect to remove the current connection and register again.', 'wpforo' ); ?> |
| 894 |
</p> |
| 895 |
<button type="button" class="button button-secondary wpforo-ai-disconnect-btn"> |
| 896 |
<span class="dashicons dashicons-dismiss"></span> |
| 897 |
<?php _e( 'Disconnect Service', 'wpforo' ); ?> |
| 898 |
</button> |
| 899 |
<button type="button" class="button button-secondary wpforo-ai-disconnect-purge-btn" style="color: #b32d2e; border-color: #b32d2e;"> |
| 900 |
<span class="dashicons dashicons-trash"></span> |
| 901 |
<?php _e( 'Disconnect and Remove All Data', 'wpforo' ); ?> |
| 902 |
</button> |
| 903 |
</div> |
| 904 |
|
| 905 |
<div class="wpforo-ai-support-info" style="margin-top: 20px;"> |
| 906 |
<p style="color: #666; font-size: 13px;"> |
| 907 |
<?php |
| 908 |
printf( |
| 909 |
__( 'Need help? %s', 'wpforo' ), |
| 910 |
'<a href="https://wpforo.com/login-register/?tab=login" target="_blank">' . __( 'Open Support Ticket', 'wpforo' ) . '</a>' |
| 911 |
); |
| 912 |
?> |
| 913 |
</p> |
| 914 |
</div> |
| 915 |
</div> |
| 916 |
</div> |
| 917 |
|
| 918 |
<!-- Video Tutorials Box --> |
| 919 |
<?php wpforo_ai_render_video_tutorials(); ?> |
| 920 |
|
| 921 |
<!-- Plans Section --> |
| 922 |
<div id="wpforo-ai-plans" class="wpforo-ai-box" style="margin-top: 20px;"> |
| 923 |
<div class="wpforo-ai-box-header"> |
| 924 |
<h2><?php _e( 'Available Plans', 'wpforo' ); ?></h2> |
| 925 |
</div> |
| 926 |
<div class="wpforo-ai-box-body"> |
| 927 |
<?php wpforo_ai_render_pricing_table( 'free_trial' ); ?> |
| 928 |
</div> |
| 929 |
</div> |
| 930 |
</div> |
| 931 |
|
| 932 |
<!-- Hidden Forms for Disconnect (triggered by JS buttons above) --> |
| 933 |
<div id="wpforo-ai-hidden-forms" style="display:none;"> |
| 934 |
<form id="wpforo-ai-disconnect-form" method="post" action=""> |
| 935 |
<?php wp_nonce_field( 'wpforo_ai_disconnect' ); ?> |
| 936 |
<input type="hidden" name="wpforo_ai_action" value="disconnect"> |
| 937 |
<div class="wpforo-ai-disconnect-warning"> |
| 938 |
<span class="dashicons dashicons-warning"></span> |
| 939 |
<p><strong><?php _e( 'Warning: This will disconnect your forum from wpForo AI service.', 'wpforo' ); ?></strong></p> |
| 940 |
<p><?php _e( 'Your credits will be preserved and restored when you reconnect. Your indexed content will be deleted after 30 days. You can reconnect anytime with the same site URL.', 'wpforo' ); ?></p> |
| 941 |
</div> |
| 942 |
<p> |
| 943 |
<label> |
| 944 |
<input type="checkbox" name="confirm" value="1" required> |
| 945 |
<?php _e( 'I understand and want to disconnect the service', 'wpforo' ); ?> |
| 946 |
</label> |
| 947 |
</p> |
| 948 |
<p> |
| 949 |
<label for="disconnect-reason"><?php _e( 'Reason (optional):', 'wpforo' ); ?></label> |
| 950 |
<textarea id="disconnect-reason" name="reason" rows="3" class="large-text" placeholder="<?php esc_attr_e( 'Help us improve by telling us why you\'re disconnecting', 'wpforo' ); ?>"></textarea> |
| 951 |
</p> |
| 952 |
</form> |
| 953 |
|
| 954 |
<form id="wpforo-ai-disconnect-purge-form" method="post" action=""> |
| 955 |
<?php wp_nonce_field( 'wpforo_ai_disconnect' ); ?> |
| 956 |
<input type="hidden" name="wpforo_ai_action" value="disconnect"> |
| 957 |
<input type="hidden" name="purge_data" value="1"> |
| 958 |
<div class="wpforo-ai-disconnect-warning" style="border-left-color: #b32d2e;"> |
| 959 |
<span class="dashicons dashicons-warning" style="color: #b32d2e;"></span> |
| 960 |
<p><strong style="color: #b32d2e;"><?php _e( 'Warning: This will permanently delete ALL your data from gVectors AI servers.', 'wpforo' ); ?></strong></p> |
| 961 |
<p><?php _e( 'This action will disconnect your forum and immediately delete all indexed content, embeddings, and tenant data from the AI service. This cannot be undone. Your credits will NOT be preserved.', 'wpforo' ); ?></p> |
| 962 |
</div> |
| 963 |
<p> |
| 964 |
<label> |
| 965 |
<input type="checkbox" name="confirm" value="1" required> |
| 966 |
<?php _e( 'I understand that all my data will be permanently deleted and want to proceed', 'wpforo' ); ?> |
| 967 |
</label> |
| 968 |
</p> |
| 969 |
<p> |
| 970 |
<label for="disconnect-purge-reason"><?php _e( 'Reason (optional):', 'wpforo' ); ?></label> |
| 971 |
<textarea id="disconnect-purge-reason" name="reason" rows="3" class="large-text" placeholder="<?php esc_attr_e( 'Help us improve by telling us why you\'re removing your data', 'wpforo' ); ?>"></textarea> |
| 972 |
</p> |
| 973 |
</form> |
| 974 |
</div> |
| 975 |
<?php |
| 976 |
} |
| 977 |
|
| 978 |
/** |
| 979 |
* Render error state (generic errors, not expiry) |
| 980 |
* |
| 981 |
* @param WP_Error|array $error Error object or status data |
| 982 |
*/ |
| 983 |
function wpforo_ai_render_error_state( $error ) { |
| 984 |
$is_wp_error = is_wp_error( $error ); |
| 985 |
$error_message = $is_wp_error ? $error->get_error_message() : __( 'Unable to connect to AI service.', 'wpforo' ); |
| 986 |
|
| 987 |
?> |
| 988 |
<div class="wpforo-ai-state wpforo-ai-error-state"> |
| 989 |
<div class="wpforo-ai-box wpforo-ai-error-box"> |
| 990 |
<div class="wpforo-ai-box-header"> |
| 991 |
<h2><?php _e( 'Connection Issue', 'wpforo' ); ?></h2> |
| 992 |
</div> |
| 993 |
<div class="wpforo-ai-box-body"> |
| 994 |
<div class="wpforo-ai-status-badge status-error"> |
| 995 |
<span class="dashicons dashicons-dismiss"></span> |
| 996 |
<?php _e( 'Error', 'wpforo' ); ?> |
| 997 |
</div> |
| 998 |
|
| 999 |
<div class="wpforo-ai-error-message"> |
| 1000 |
<p><strong><?php echo esc_html( $error_message ); ?></strong></p> |
| 1001 |
</div> |
| 1002 |
|
| 1003 |
<div class="wpforo-ai-error-actions"> |
| 1004 |
<form method="post" action=""> |
| 1005 |
<?php wp_nonce_field( 'wpforo_ai_refresh_status' ); ?> |
| 1006 |
<input type="hidden" name="wpforo_ai_action" value="refresh_status"> |
| 1007 |
<button type="submit" class="button button-primary"> |
| 1008 |
<span class="dashicons dashicons-update"></span> |
| 1009 |
<?php _e( 'Retry Connection', 'wpforo' ); ?> |
| 1010 |
</button> |
| 1011 |
</form> |
| 1012 |
|
| 1013 |
<?php if ( ! $is_wp_error ) : ?> |
| 1014 |
<?php |
| 1015 |
$err_provider = get_option( 'wpforo_ai_payment_provider', 'freemius' ); |
| 1016 |
?> |
| 1017 |
<a href="<?php echo esc_url( wpforo_ai_get_manage_subscription_url( $err_provider ) ); ?>" class="button button-secondary wpf-manage-subscription wpf-provider-<?php echo esc_attr( $err_provider ); ?>" target="_blank"> |
| 1018 |
<span class="dashicons dashicons-admin-generic"></span> |
| 1019 |
<?php printf( __( 'Manage Subscription (%s)', 'wpforo' ), esc_html( ucfirst( $err_provider ) ) ); ?> |
| 1020 |
</a> |
| 1021 |
<?php endif; ?> |
| 1022 |
</div> |
| 1023 |
|
| 1024 |
<div class="wpforo-ai-support-info"> |
| 1025 |
<p> |
| 1026 |
<?php |
| 1027 |
printf( |
| 1028 |
__( 'Need help? %s', 'wpforo' ), |
| 1029 |
'<a href="https://wpforo.com/login-register/?tab=login" target="_blank">' . __( 'Open Support Ticket', 'wpforo' ) . '</a>' |
| 1030 |
); |
| 1031 |
?> |
| 1032 |
</p> |
| 1033 |
</div> |
| 1034 |
</div> |
| 1035 |
</div> |
| 1036 |
</div> |
| 1037 |
<?php |
| 1038 |
} |
| 1039 |
|
| 1040 |
/** |
| 1041 |
* Check if a feature is enabled based on plan hierarchy |
| 1042 |
* |
| 1043 |
* @param string $current_plan Current user's plan |
| 1044 |
* @param string $feature_plan Feature's required plan |
| 1045 |
* @return bool True if feature should be enabled |
| 1046 |
*/ |
| 1047 |
function wpforo_ai_is_feature_enabled_by_plan( $current_plan, $feature_plan ) { |
| 1048 |
// Plan hierarchy (lower to higher) |
| 1049 |
$plan_hierarchy = array( |
| 1050 |
'free_trial' => 0, |
| 1051 |
'starter' => 0, // Starter and free_trial are same level |
| 1052 |
'professional' => 1, |
| 1053 |
'business' => 2, |
| 1054 |
'enterprise' => 3, |
| 1055 |
); |
| 1056 |
|
| 1057 |
$current_level = isset( $plan_hierarchy[ $current_plan ] ) ? $plan_hierarchy[ $current_plan ] : 0; |
| 1058 |
$required_level = isset( $plan_hierarchy[ $feature_plan ] ) ? $plan_hierarchy[ $feature_plan ] : 0; |
| 1059 |
|
| 1060 |
// Feature is enabled if current plan level >= required plan level |
| 1061 |
return $current_level >= $required_level; |
| 1062 |
} |
| 1063 |
|
| 1064 |
/** |
| 1065 |
* Render features list |
| 1066 |
* |
| 1067 |
* @param array $enabled_features List of enabled feature IDs |
| 1068 |
* @param array $usage Usage statistics per feature |
| 1069 |
* @param bool $is_free_trial Whether on free trial |
| 1070 |
* @param array $status Tenant status data from API (required for plan detection) |
| 1071 |
*/ |
| 1072 |
function wpforo_ai_render_features_list( $enabled_features, $usage, $is_free_trial, $status = null ) { |
| 1073 |
$all_features = wpforo_ai_get_all_features(); |
| 1074 |
|
| 1075 |
// Ensure $enabled_features is an array |
| 1076 |
if ( ! is_array( $enabled_features ) ) { |
| 1077 |
$enabled_features = []; |
| 1078 |
} |
| 1079 |
|
| 1080 |
// Ensure $usage is an array |
| 1081 |
if ( ! is_array( $usage ) ) { |
| 1082 |
$usage = []; |
| 1083 |
} |
| 1084 |
|
| 1085 |
// Get current plan from status (passed from parent function) |
| 1086 |
$current_plan = 'free_trial'; |
| 1087 |
if ( isset( $status['subscription']['plan'] ) ) { |
| 1088 |
$current_plan = $status['subscription']['plan']; |
| 1089 |
} elseif ( ! $is_free_trial ) { |
| 1090 |
// If not free trial but no plan set, assume starter |
| 1091 |
$current_plan = 'starter'; |
| 1092 |
} |
| 1093 |
|
| 1094 |
// Group features by plan |
| 1095 |
$features_by_plan = [ |
| 1096 |
'starter' => [], |
| 1097 |
'professional' => [], |
| 1098 |
'business' => [], |
| 1099 |
'enterprise' => [], |
| 1100 |
]; |
| 1101 |
|
| 1102 |
foreach ( $all_features as $feature_id => $feature ) { |
| 1103 |
$feature_plan = isset( $feature['plan'] ) ? $feature['plan'] : 'professional'; |
| 1104 |
if ( isset( $features_by_plan[ $feature_plan ] ) ) { |
| 1105 |
$features_by_plan[ $feature_plan ][ $feature_id ] = $feature; |
| 1106 |
} |
| 1107 |
} |
| 1108 |
|
| 1109 |
// Plan display names |
| 1110 |
$plan_names = [ |
| 1111 |
'starter' => __( 'Starter Features', 'wpforo' ), |
| 1112 |
'professional' => __( 'Professional Features', 'wpforo' ), |
| 1113 |
'business' => __( 'Business Features', 'wpforo' ), |
| 1114 |
'enterprise' => __( 'Enterprise Features', 'wpforo' ), |
| 1115 |
]; |
| 1116 |
|
| 1117 |
// Render accordion for each plan |
| 1118 |
echo '<div class="wpforo-ai-features-accordion">'; |
| 1119 |
|
| 1120 |
foreach ( $features_by_plan as $plan_level => $features ) { |
| 1121 |
if ( empty( $features ) ) { |
| 1122 |
continue; |
| 1123 |
} |
| 1124 |
|
| 1125 |
$plan_id = 'plan-' . $plan_level; |
| 1126 |
$is_plan_unlocked = wpforo_ai_is_feature_enabled_by_plan( $current_plan, $plan_level ); |
| 1127 |
$is_current_plan = ( $current_plan === $plan_level ); |
| 1128 |
$plan_status_icon = $is_plan_unlocked ? 'dashicons-yes-alt' : 'dashicons-lock'; |
| 1129 |
$plan_status_class = $is_plan_unlocked ? 'plan-unlocked' : 'plan-locked'; |
| 1130 |
|
| 1131 |
echo '<div class="accordion-item ' . esc_attr( $plan_status_class ) . ( $is_current_plan ? ' current-plan' : '' ) . '">'; |
| 1132 |
echo '<button class="accordion-header" type="button" data-plan="' . esc_attr( $plan_level ) . '" aria-expanded="false" aria-controls="' . esc_attr( $plan_id ) . '">'; |
| 1133 |
echo '<span class="accordion-status-icon dashicons ' . esc_attr( $plan_status_icon ) . '"></span>'; |
| 1134 |
echo '<span class="accordion-title">' . esc_html( $plan_names[ $plan_level ] ) . '</span>'; |
| 1135 |
echo '<span class="accordion-icon dashicons dashicons-arrow-down-alt2"></span>'; |
| 1136 |
echo '</button>'; |
| 1137 |
|
| 1138 |
echo '<div class="accordion-content" id="' . esc_attr( $plan_id ) . '" style="display: none;">'; |
| 1139 |
echo '<ul class="wpforo-ai-features-list">'; |
| 1140 |
|
| 1141 |
foreach ( $features as $feature_id => $feature ) { |
| 1142 |
// Check if feature is enabled based on plan hierarchy |
| 1143 |
$is_enabled = in_array( $feature_id, $enabled_features ) || $is_plan_unlocked; |
| 1144 |
$usage_count = (int) wpfval( $usage, $feature_id, 0 ); |
| 1145 |
$css_class = $is_enabled ? 'feature-enabled' : 'feature-locked'; |
| 1146 |
|
| 1147 |
echo '<li class="' . esc_attr( $css_class ) . '">'; |
| 1148 |
echo '<span class="feature-icon">' . wpforo_ai_get_feature_icon( $feature_id ) . '</span>'; |
| 1149 |
echo '<div class="feature-info">'; |
| 1150 |
echo '<strong>' . esc_html( $feature['name'] ) . '</strong>'; |
| 1151 |
echo '<p>' . esc_html( $feature['description'] ) . '</p>'; |
| 1152 |
echo '</div>'; |
| 1153 |
|
| 1154 |
|
| 1155 |
|
| 1156 |
echo '</li>'; |
| 1157 |
} |
| 1158 |
|
| 1159 |
echo '</ul>'; |
| 1160 |
echo '</div>'; // .accordion-content |
| 1161 |
echo '</div>'; // .accordion-item |
| 1162 |
} |
| 1163 |
|
| 1164 |
echo '</div>'; // .wpforo-ai-features-accordion |
| 1165 |
} |
| 1166 |
|
| 1167 |
/** |
| 1168 |
* Render features preview list (for "What You'll Get" section) |
| 1169 |
* Shows all features except enterprise plan when no API key is registered |
| 1170 |
*/ |
| 1171 |
function wpforo_ai_render_features_preview() { |
| 1172 |
$features = wpforo_ai_get_all_features(); |
| 1173 |
|
| 1174 |
// Only WooCommerce Products indexing is coming soon |
| 1175 |
$coming_soon_features = [ 'woocommerce_products_indexing' ]; |
| 1176 |
|
| 1177 |
// Plan display names and colors |
| 1178 |
$plan_labels = [ |
| 1179 |
'starter' => [ 'label' => __( 'Free / Starter', 'wpforo' ), 'class' => 'plan-starter' ], |
| 1180 |
'professional' => [ 'label' => __( 'Professional', 'wpforo' ), 'class' => 'plan-professional' ], |
| 1181 |
'business' => [ 'label' => __( 'Business', 'wpforo' ), 'class' => 'plan-business' ], |
| 1182 |
'enterprise' => [ 'label' => __( 'Enterprise', 'wpforo' ), 'class' => 'plan-enterprise' ], |
| 1183 |
]; |
| 1184 |
|
| 1185 |
echo '<ul class="wpforo-ai-features-list wpforo-ai-features-preview">'; |
| 1186 |
|
| 1187 |
foreach ( $features as $feature_id => $feature ) { |
| 1188 |
// Skip enterprise features in preview |
| 1189 |
if ( isset( $feature['plan'] ) && $feature['plan'] === 'enterprise' ) { |
| 1190 |
continue; |
| 1191 |
} |
| 1192 |
|
| 1193 |
$is_coming_soon = in_array( $feature_id, $coming_soon_features, true ); |
| 1194 |
$class = $is_coming_soon ? 'feature-pending' : 'feature-enabled'; |
| 1195 |
$plan = $feature['plan'] ?? 'starter'; |
| 1196 |
$plan_info = $plan_labels[ $plan ] ?? $plan_labels['starter']; |
| 1197 |
|
| 1198 |
echo '<li class="' . esc_attr( $class ) . ' ' . esc_attr( $plan_info['class'] ) . '">'; |
| 1199 |
|
| 1200 |
// Feature icon |
| 1201 |
echo '<span class="feature-icon">' . wpforo_ai_get_feature_icon( $feature_id ) . '</span>'; |
| 1202 |
|
| 1203 |
// Feature info |
| 1204 |
echo '<div class="feature-info">'; |
| 1205 |
echo '<strong>' . esc_html( $feature['name'] ) . '</strong>'; |
| 1206 |
if ( $is_coming_soon ) { |
| 1207 |
echo '<span class="coming-soon-badge">' . esc_html__( 'Coming Soon', 'wpforo' ) . '</span>'; |
| 1208 |
} |
| 1209 |
echo '<p>' . esc_html( $feature['description'] ) . '</p>'; |
| 1210 |
echo '</div>'; |
| 1211 |
|
| 1212 |
// Plan badge |
| 1213 |
echo '<span class="plan-badge ' . esc_attr( $plan_info['class'] ) . '">' . esc_html( $plan_info['label'] ) . '</span>'; |
| 1214 |
|
| 1215 |
echo '</li>'; |
| 1216 |
} |
| 1217 |
|
| 1218 |
// Add "More Coming Soon" teaser |
| 1219 |
echo '<li class="feature-teaser">'; |
| 1220 |
echo '<span class="feature-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg></span>'; |
| 1221 |
echo '<div class="feature-info">'; |
| 1222 |
echo '<strong>' . __( 'And Many More AI Features Coming Soon!', 'wpforo' ) . '</strong>'; |
| 1223 |
echo '<p>' . __( 'This is just the beginning. We\'re actively developing additional AI features including sentiment analysis, member retention predictions, personalized content feeds, and advanced automation tools. Join our growing community and help shape the future of forum AI.', 'wpforo' ) . '</p>'; |
| 1224 |
echo '</div>'; |
| 1225 |
echo '<span class="plan-badge plan-enterprise">' . esc_html__( 'For All Plans', 'wpforo' ) . '</span>'; |
| 1226 |
echo '</li>'; |
| 1227 |
|
| 1228 |
echo '</ul>'; |
| 1229 |
} |
| 1230 |
|
| 1231 |
/** |
| 1232 |
* Render Getting Started Steps Box |
| 1233 |
* |
| 1234 |
* Displays a visual progress indicator showing the steps to use wpForo AI. |
| 1235 |
* First step (Connect) is marked as completed when connected, shows "1" when not. |
| 1236 |
* |
| 1237 |
* @param bool $is_connected Whether the user is connected to AI services |
| 1238 |
*/ |
| 1239 |
function wpforo_ai_render_getting_started_steps( $is_connected = true ) { |
| 1240 |
// Build URLs for each step |
| 1241 |
$indexing_url = admin_url( 'admin.php?page=wpforo-ai&tab=rag_indexing' ); |
| 1242 |
$settings_url = admin_url( 'admin.php?page=wpforo-settings&wpf_tab=ai' ); |
| 1243 |
$spam_url = admin_url( 'admin.php?page=wpforo-settings&wpf_tab=ai#moderation_spam' ); |
| 1244 |
$forum_url = wpforo_home_url(); |
| 1245 |
$logs_url = admin_url( 'admin.php?page=wpforo-ai&tab=ai_logs' ); |
| 1246 |
?> |
| 1247 |
<div class="wpforo-ai-box wpforo-ai-getting-started-box"> |
| 1248 |
<div class="wpforo-ai-box-header"> |
| 1249 |
<h2><?php _e( 'Getting Started with wpForo AI', 'wpforo' ); ?></h2> |
| 1250 |
</div> |
| 1251 |
<div class="wpforo-ai-box-body"> |
| 1252 |
<div class="wpforo-ai-steps"> |
| 1253 |
<div class="wpforo-ai-step <?php echo $is_connected ? 'completed' : ''; ?>"> |
| 1254 |
<div class="wpforo-ai-step-icon"> |
| 1255 |
<?php if ( $is_connected ) : ?> |
| 1256 |
<span class="dashicons dashicons-yes-alt"></span> |
| 1257 |
<?php else : ?> |
| 1258 |
<span class="wpforo-ai-step-number">1</span> |
| 1259 |
<?php endif; ?> |
| 1260 |
</div> |
| 1261 |
<div class="wpforo-ai-step-label"><?php _e( 'Connect wpForo AI', 'wpforo' ); ?></div> |
| 1262 |
</div> |
| 1263 |
<div class="wpforo-ai-step-connector"></div> |
| 1264 |
<?php if ( $is_connected ) : ?> |
| 1265 |
<a href="<?php echo esc_url( $indexing_url ); ?>" class="wpforo-ai-step"> |
| 1266 |
<?php else : ?> |
| 1267 |
<div class="wpforo-ai-step"> |
| 1268 |
<?php endif; ?> |
| 1269 |
<div class="wpforo-ai-step-icon"> |
| 1270 |
<span class="wpforo-ai-step-number">2</span> |
| 1271 |
</div> |
| 1272 |
<div class="wpforo-ai-step-label" style="color: rgb(214, 39, 224);"><?php _e( 'Index Forum Content', 'wpforo' ); ?></div> |
| 1273 |
<?php echo $is_connected ? '</a>' : '</div>'; ?> |
| 1274 |
<div class="wpforo-ai-step-connector"></div> |
| 1275 |
<?php if ( $is_connected ) : ?> |
| 1276 |
<a href="<?php echo esc_url( $settings_url ); ?>" class="wpforo-ai-step"> |
| 1277 |
<?php else : ?> |
| 1278 |
<div class="wpforo-ai-step"> |
| 1279 |
<?php endif; ?> |
| 1280 |
<div class="wpforo-ai-step-icon"> |
| 1281 |
<span class="wpforo-ai-step-number">3</span> |
| 1282 |
</div> |
| 1283 |
<div class="wpforo-ai-step-label"><?php _e( 'Manage AI Features', 'wpforo' ); ?></div> |
| 1284 |
<?php echo $is_connected ? '</a>' : '</div>'; ?> |
| 1285 |
<div class="wpforo-ai-step-connector"></div> |
| 1286 |
<?php if ( $is_connected ) : ?> |
| 1287 |
<a href="<?php echo esc_url( $forum_url ); ?>" class="wpforo-ai-step" target="_blank"> |
| 1288 |
<?php else : ?> |
| 1289 |
<div class="wpforo-ai-step"> |
| 1290 |
<?php endif; ?> |
| 1291 |
<div class="wpforo-ai-step-icon"> |
| 1292 |
<span class="wpforo-ai-step-number">4</span> |
| 1293 |
</div> |
| 1294 |
<div class="wpforo-ai-step-label"><?php _e( 'Use', 'wpforo' ); ?><br><?php _e( 'AI Features', 'wpforo' ); ?></div> |
| 1295 |
<?php echo $is_connected ? '</a>' : '</div>'; ?> |
| 1296 |
<div class="wpforo-ai-step-connector"></div> |
| 1297 |
<?php if ( $is_connected ) : ?> |
| 1298 |
<a href="<?php echo esc_url( $spam_url ); ?>" class="wpforo-ai-step"> |
| 1299 |
<?php else : ?> |
| 1300 |
<div class="wpforo-ai-step"> |
| 1301 |
<?php endif; ?> |
| 1302 |
<div class="wpforo-ai-step-icon"> |
| 1303 |
<span class="wpforo-ai-step-number">5</span> |
| 1304 |
</div> |
| 1305 |
<div class="wpforo-ai-step-label"><?php _e( 'Enable AI Spam Protection', 'wpforo' ); ?></div> |
| 1306 |
<?php echo $is_connected ? '</a>' : '</div>'; ?> |
| 1307 |
<div class="wpforo-ai-step-connector"></div> |
| 1308 |
<?php if ( $is_connected ) : ?> |
| 1309 |
<a href="<?php echo esc_url( $logs_url ); ?>" class="wpforo-ai-step"> |
| 1310 |
<?php else : ?> |
| 1311 |
<div class="wpforo-ai-step"> |
| 1312 |
<?php endif; ?> |
| 1313 |
<div class="wpforo-ai-step-icon"> |
| 1314 |
<span class="wpforo-ai-step-number">6</span> |
| 1315 |
</div> |
| 1316 |
<div class="wpforo-ai-step-label"><?php _e( 'Monitor AI Usage', 'wpforo' ); ?></div> |
| 1317 |
<?php echo $is_connected ? '</a>' : '</div>'; ?> |
| 1318 |
</div> |
| 1319 |
<div class="wpforo-ai-privacy-note"> |
| 1320 |
<p><span class="dashicons dashicons-shield" style="color: #0073aa;"></span> <strong><?php _e( 'Your Data Stays Yours', 'wpforo' ); ?></strong></p> |
| 1321 |
<ul> |
| 1322 |
<li><strong style="color: rgb(214, 39, 224);"><?php _e( 'Forum content indexing', 'wpforo' ); ?></strong> <?php _e( 'converts your forum content into mathematical vectors (embeddings) to power AI search and features.', 'wpforo' ); ?></li> |
| 1323 |
<li><?php _e( 'Your data is never used to train AI models. We use pre-trained models from Amazon Bedrock.', 'wpforo' ); ?></li> |
| 1324 |
<li><?php _e( 'By default your data embeddings are stored locally in your WordPress database.', 'wpforo' ); ?></li> |
| 1325 |
</ul> |
| 1326 |
</div> |
| 1327 |
<div class="wpforo-ai-steps-cta"> |
| 1328 |
<a href="https://wpforo.com/docs/wpforo-v3/ai-features/#getting-started" target="_blank" class="button button-primary button-hero"> |
| 1329 |
<span class="dashicons dashicons-book" style="vertical-align: middle; margin-right: 5px;"></span> |
| 1330 |
<?php _e( 'Read AI Features Documentation', 'wpforo' ); ?> |
| 1331 |
</a> |
| 1332 |
</div> |
| 1333 |
</div> |
| 1334 |
</div> |
| 1335 |
<style> |
| 1336 |
.wpforo-ai-privacy-note { |
| 1337 |
background: #f0f7fc; |
| 1338 |
border-left: 4px solid #0073aa; |
| 1339 |
padding: 15px 20px; |
| 1340 |
margin: 20px 0; |
| 1341 |
border-radius: 0 4px 4px 0; |
| 1342 |
} |
| 1343 |
.wpforo-ai-privacy-note p { |
| 1344 |
margin: 0 0 10px 0; |
| 1345 |
font-size: 14px; |
| 1346 |
} |
| 1347 |
.wpforo-ai-privacy-note ul { |
| 1348 |
margin: 0; |
| 1349 |
padding-left: 20px; |
| 1350 |
} |
| 1351 |
.wpforo-ai-privacy-note li { |
| 1352 |
margin-bottom: 5px; |
| 1353 |
font-size: 13px; |
| 1354 |
color: #444; |
| 1355 |
} |
| 1356 |
.wpforo-ai-getting-started-box { |
| 1357 |
margin-bottom: 20px; |
| 1358 |
} |
| 1359 |
.wpforo-ai-steps-cta { |
| 1360 |
text-align: center; |
| 1361 |
margin-top: 10px; |
| 1362 |
padding-top: 20px; |
| 1363 |
border-top: 1px solid #e0e0e0; |
| 1364 |
} |
| 1365 |
.wpforo-ai-steps-cta .button-hero { |
| 1366 |
font-size: 15px; |
| 1367 |
padding: 10px 25px; |
| 1368 |
height: auto; |
| 1369 |
} |
| 1370 |
.wpforo-ai-steps { |
| 1371 |
display: flex; |
| 1372 |
align-items: center; |
| 1373 |
justify-content: center; |
| 1374 |
padding: 30px 20px; |
| 1375 |
gap: 0; |
| 1376 |
} |
| 1377 |
.wpforo-ai-step { |
| 1378 |
display: flex; |
| 1379 |
flex-direction: column; |
| 1380 |
align-items: center; |
| 1381 |
text-decoration: none; |
| 1382 |
color: #1d2327; |
| 1383 |
transition: transform 0.2s ease; |
| 1384 |
} |
| 1385 |
a.wpforo-ai-step:hover { |
| 1386 |
transform: translateY(-3px); |
| 1387 |
} |
| 1388 |
a.wpforo-ai-step:hover .wpforo-ai-step-icon { |
| 1389 |
background: #2271b1; |
| 1390 |
color: #fff; |
| 1391 |
border-color: #2271b1; |
| 1392 |
} |
| 1393 |
.wpforo-ai-step-icon { |
| 1394 |
width: 50px; |
| 1395 |
height: 50px; |
| 1396 |
border-radius: 50%; |
| 1397 |
background: #f0f0f1; |
| 1398 |
border: 2px solid #c3c4c7; |
| 1399 |
display: flex; |
| 1400 |
align-items: center; |
| 1401 |
justify-content: center; |
| 1402 |
margin-bottom: 10px; |
| 1403 |
transition: all 0.2s ease; |
| 1404 |
} |
| 1405 |
a.wpforo-ai-step .wpforo-ai-step-icon { |
| 1406 |
background: #edfaef; |
| 1407 |
border-color: #00a32a; |
| 1408 |
} |
| 1409 |
a.wpforo-ai-step .wpforo-ai-step-number { |
| 1410 |
color: #00a32a; |
| 1411 |
} |
| 1412 |
.wpforo-ai-step.completed .wpforo-ai-step-icon { |
| 1413 |
background: #00a32a; |
| 1414 |
border-color: #00a32a; |
| 1415 |
color: #fff; |
| 1416 |
} |
| 1417 |
.wpforo-ai-step.completed .wpforo-ai-step-icon .dashicons { |
| 1418 |
font-size: 24px; |
| 1419 |
width: 24px; |
| 1420 |
height: 24px; |
| 1421 |
} |
| 1422 |
.wpforo-ai-step-number { |
| 1423 |
font-size: 18px; |
| 1424 |
font-weight: 600; |
| 1425 |
color: #50575e; |
| 1426 |
} |
| 1427 |
a.wpforo-ai-step:hover .wpforo-ai-step-number { |
| 1428 |
color: #fff; |
| 1429 |
} |
| 1430 |
.wpforo-ai-step-label { |
| 1431 |
font-size: 13px; |
| 1432 |
font-weight: 500; |
| 1433 |
text-align: center; |
| 1434 |
max-width: 100px; |
| 1435 |
line-height: 1.3; |
| 1436 |
} |
| 1437 |
.wpforo-ai-step-connector { |
| 1438 |
width: 40px; |
| 1439 |
height: 2px; |
| 1440 |
background: #c3c4c7; |
| 1441 |
margin: 0 5px; |
| 1442 |
margin-bottom: 30px; |
| 1443 |
} |
| 1444 |
@media (max-width: 900px) { |
| 1445 |
.wpforo-ai-steps { |
| 1446 |
flex-wrap: wrap; |
| 1447 |
gap: 15px; |
| 1448 |
} |
| 1449 |
.wpforo-ai-step-connector { |
| 1450 |
display: none; |
| 1451 |
} |
| 1452 |
} |
| 1453 |
</style> |
| 1454 |
<?php |
| 1455 |
} |
| 1456 |
|
| 1457 |
/** |
| 1458 |
* Render Video Tutorials Box |
| 1459 |
* |
| 1460 |
* Displays 3 YouTube video tutorials in a 3-column grid layout. |
| 1461 |
* Shown on the AI Features overview page between connection status and features list. |
| 1462 |
*/ |
| 1463 |
function wpforo_ai_render_video_tutorials() { |
| 1464 |
$videos = [ |
| 1465 |
[ |
| 1466 |
'url' => 'https://www.youtube.com/watch?v=ZmNEAYSWg8M', |
| 1467 |
'title' => __( 'wpForo AI Search', 'wpforo' ), |
| 1468 |
], |
| 1469 |
[ |
| 1470 |
'url' => 'https://www.youtube.com/watch?v=Pq5BvlrkXwE', |
| 1471 |
'title' => __( 'wpForo AI Topic Summary', 'wpforo' ), |
| 1472 |
], |
| 1473 |
[ |
| 1474 |
'url' => 'https://www.youtube.com/watch?v=2NmKtJO6miQ', |
| 1475 |
'title' => __( 'wpForo AI Translation', 'wpforo' ), |
| 1476 |
], |
| 1477 |
]; |
| 1478 |
?> |
| 1479 |
<div class="wpforo-ai-box wpforo-ai-video-tutorials-box"> |
| 1480 |
<div class="wpforo-ai-box-header"> |
| 1481 |
<h2><?php _e( 'wpForo AI Features in Action', 'wpforo' ); ?></h2> |
| 1482 |
</div> |
| 1483 |
<div class="wpforo-ai-box-body"> |
| 1484 |
<div class="wpforo-ai-videos-grid"> |
| 1485 |
<?php foreach ( $videos as $video ) : ?> |
| 1486 |
<div class="wpforo-ai-video-item"> |
| 1487 |
<div class="wpforo-ai-video-wrapper"> |
| 1488 |
<?php echo wp_oembed_get( $video['url'] ); ?> |
| 1489 |
</div> |
| 1490 |
<h4 class="wpforo-ai-video-title"><?php echo esc_html( $video['title'] ); ?></h4> |
| 1491 |
</div> |
| 1492 |
<?php endforeach; ?> |
| 1493 |
</div> |
| 1494 |
<div class="wpforo-ai-videos-cta"> |
| 1495 |
<a href="https://wpforo.com/#ai-features" target="_blank" class="button button-primary button-hero"> |
| 1496 |
<span class="dashicons dashicons-video-alt3" style="vertical-align: middle; margin-right: 5px;"></span> |
| 1497 |
<?php _e( 'See All AI Features', 'wpforo' ); ?> |
| 1498 |
</a> |
| 1499 |
</div> |
| 1500 |
</div> |
| 1501 |
</div> |
| 1502 |
<style> |
| 1503 |
.wpforo-ai-video-tutorials-box { |
| 1504 |
margin-bottom: 20px; |
| 1505 |
} |
| 1506 |
.wpforo-ai-videos-cta { |
| 1507 |
text-align: center; |
| 1508 |
margin-top: 20px; |
| 1509 |
padding-top: 20px; |
| 1510 |
border-top: 1px solid #e0e0e0; |
| 1511 |
} |
| 1512 |
.wpforo-ai-videos-cta .button-hero { |
| 1513 |
font-size: 15px; |
| 1514 |
padding: 10px 25px; |
| 1515 |
height: auto; |
| 1516 |
} |
| 1517 |
.wpforo-ai-videos-grid { |
| 1518 |
display: grid; |
| 1519 |
grid-template-columns: repeat(3, 1fr); |
| 1520 |
gap: 20px; |
| 1521 |
} |
| 1522 |
.wpforo-ai-video-item { |
| 1523 |
background: #f9f9f9; |
| 1524 |
border-radius: 8px; |
| 1525 |
overflow: hidden; |
| 1526 |
} |
| 1527 |
.wpforo-ai-video-wrapper { |
| 1528 |
position: relative; |
| 1529 |
padding-bottom: 56.25%; |
| 1530 |
height: 0; |
| 1531 |
overflow: hidden; |
| 1532 |
} |
| 1533 |
.wpforo-ai-video-wrapper iframe { |
| 1534 |
position: absolute; |
| 1535 |
top: 0; |
| 1536 |
left: 0; |
| 1537 |
width: 100%; |
| 1538 |
height: 100%; |
| 1539 |
border-radius: 8px 8px 0 0; |
| 1540 |
} |
| 1541 |
.wpforo-ai-video-title { |
| 1542 |
margin: 0; |
| 1543 |
padding: 12px 15px; |
| 1544 |
font-size: 14px; |
| 1545 |
font-weight: 600; |
| 1546 |
color: #1d2327; |
| 1547 |
text-align: center; |
| 1548 |
background: #fff; |
| 1549 |
border-top: 1px solid #e0e0e0; |
| 1550 |
} |
| 1551 |
@media (max-width: 1200px) { |
| 1552 |
.wpforo-ai-videos-grid { |
| 1553 |
grid-template-columns: repeat(2, 1fr); |
| 1554 |
} |
| 1555 |
} |
| 1556 |
@media (max-width: 782px) { |
| 1557 |
.wpforo-ai-videos-grid { |
| 1558 |
grid-template-columns: 1fr; |
| 1559 |
} |
| 1560 |
} |
| 1561 |
</style> |
| 1562 |
<?php |
| 1563 |
} |
| 1564 |
|
| 1565 |
/** |
| 1566 |
* Get all available features with metadata |
| 1567 |
* |
| 1568 |
* @return array Features array |
| 1569 |
*/ |
| 1570 |
function wpforo_ai_get_all_features() { |
| 1571 |
return apply_filters( 'wpforo_ai_features', [ |
| 1572 |
'content_indexing' => [ |
| 1573 |
'name' => __( 'AI Knowledge Generation - Forum Content Indexing & Vectorization', 'wpforo' ), |
| 1574 |
'description' => __( 'Index forum content to build a searchable vector database optimized for Retrieval Augmented Generation (RAG). This feature transforms unstructured forum discussions, threads, and posts into semantic vectors, enabling AI that truly understands your domain, products, and audience.', 'wpforo' ), |
| 1575 |
'plan' => 'starter', |
| 1576 |
'preview' => false, |
| 1577 |
], |
| 1578 |
'vector_db_local_storage' => [ |
| 1579 |
'name' => __( 'AI Indexed Vector Database - Local Storage', 'wpforo' ), |
| 1580 |
'description' => __( 'Store AI-generated vector embeddings locally on your WordPress server. Perfect for smaller forums or sites with storage capacity. Vectors are stored in your database, giving you full control over your data while enabling semantic search and AI features without external dependencies.', 'wpforo' ), |
| 1581 |
'plan' => 'starter', |
| 1582 |
'preview' => false, |
| 1583 |
], |
| 1584 |
'semantic_search' => [ |
| 1585 |
'name' => __( "AI Powered Semantic Search", 'wpforo' ), |
| 1586 |
'description' => __( "Traditional search fails when users don't know exact keywords. Stop losing members to \"no results found\". AI-powered semantic search understands what users mean, not just what they type. Find relevant discussions even with different wording, typos, or synonyms—delivering answers that actually help.", 'wpforo' ), |
| 1587 |
'plan' => 'starter', |
| 1588 |
'preview' => true, |
| 1589 |
], |
| 1590 |
'search_enhance' => [ |
| 1591 |
'name' => __( 'AI Search Enhancement', 'wpforo' ), |
| 1592 |
'description' => __( 'Elevate search results with AI-powered summaries and recommendations. When users search, AI analyzes the results and generates a contextual summary explaining how each result relates to the query. Get intelligent suggestions for related topics and better answers instantly.', 'wpforo' ), |
| 1593 |
'plan' => 'starter', |
| 1594 |
'preview' => true, |
| 1595 |
], |
| 1596 |
'topic_summary' => [ |
| 1597 |
'name' => __( 'AI Topic Summarization', 'wpforo' ), |
| 1598 |
'description' => __( 'Get instant AI-generated summaries of long forum discussions. Help members quickly understand the key points, main conclusions, and important details of any topic without reading through hundreds of replies. Perfect for catching up on active discussions or reviewing complex threads at a glance.', 'wpforo' ), |
| 1599 |
'plan' => 'starter', |
| 1600 |
'preview' => true, |
| 1601 |
], |
| 1602 |
'smart_topic_suggestions' => [ |
| 1603 |
'name' => __( 'AI Topic Suggestions', 'wpforo' ), |
| 1604 |
'description' => __( 'Enhance topic creation with intelligent suggestions. AI analyzes what members are typing and instantly recommends similar existing discussions, related topics, and potential answers. Reduce duplicate posts, improve search visibility, and help users discover solutions before they even ask—all in real-time.', 'wpforo' ), |
| 1605 |
'plan' => 'starter', |
| 1606 |
'preview' => true, |
| 1607 |
], |
| 1608 |
'multi_language_translation' => [ |
| 1609 |
'name' => __( 'AI Multi-Language Translation', 'wpforo' ), |
| 1610 |
'description' => __( 'Break language barriers and grow your global community. No more limiting your community to one language. Multi-language AI translation lets members from anywhere participate naturally. Each user sees content in their language, posts in their language, and AI bridges the gap—no manual translation needed.', 'wpforo' ), |
| 1611 |
'plan' => 'starter', |
| 1612 |
'preview' => true, |
| 1613 |
], |
| 1614 |
'ai_spam_detection' => [ |
| 1615 |
'name' => __( 'AI Moderation - Spam Detection and User Banning', 'wpforo' ), |
| 1616 |
'description' => __( 'Keep your forum clean with intelligent spam detection. AI automatically identifies spam content after post submission, blocking malicious posts before they appear while learning from your moderation decisions to improve accuracy.', 'wpforo' ), |
| 1617 |
'plan' => 'starter', |
| 1618 |
'preview' => true, |
| 1619 |
], |
| 1620 |
'ai_toxicity_detection' => [ |
| 1621 |
'name' => __( 'AI Moderation - Content Safety & Toxicity Detection', 'wpforo' ), |
| 1622 |
'description' => __( 'Protect your community from harmful content with advanced toxicity detection. AI analyzes posts for hate speech, harassment, personal attacks, threats, and other toxic behavior. Configurable severity thresholds let you set how aggressively to filter content, while automated actions like unapproval or user banning help maintain a respectful environment without constant manual moderation.', 'wpforo' ), |
| 1623 |
'plan' => 'starter', |
| 1624 |
'preview' => false, |
| 1625 |
], |
| 1626 |
'ai_rule_compliance' => [ |
| 1627 |
'name' => __( 'AI Moderation - Rule Compliance & Policy Enforcement', 'wpforo' ), |
| 1628 |
'description' => __( 'Automatically enforce your forum rules and community guidelines. AI checks every post against configurable policies including topic relevance, promotional content restrictions, and illegal content detection. Smart keyword pre-filtering catches obvious violations instantly without API calls, while nuanced cases receive full AI analysis. Define custom rules for your community and let AI ensure members stay on topic and follow your guidelines.', 'wpforo' ), |
| 1629 |
'plan' => 'starter', |
| 1630 |
'preview' => false, |
| 1631 |
], |
| 1632 |
'forum_image_indexing' => [ |
| 1633 |
'name' => __( 'AI Knowledge Generation - Forum Image Indexing & Vectorization', 'wpforo' ), |
| 1634 |
'description' => __( 'Unlock the power of visual content in your forum. AI automatically analyzes images embedded in posts—screenshots, diagrams, infographics, product photos—and generates rich semantic embeddings. Visual information is indexed alongside text, enabling AI search and chat to understand and retrieve content based on what images show, not just surrounding text. Perfect for technical forums, support communities, and visual-heavy discussions.', 'wpforo' ), |
| 1635 |
'plan' => 'professional', |
| 1636 |
'preview' => false, |
| 1637 |
], |
| 1638 |
'forum_document_indexing' => [ |
| 1639 |
'name' => __( 'AI Knowledge Generation - Forum Document Indexing & Vectorization', 'wpforo' ), |
| 1640 |
'description' => __( 'Transform document attachments into searchable knowledge. AI automatically extracts text from PDF, Word (DOCX), PowerPoint (PPTX), RTF, and plain text files attached to forum posts. Extracted content is chunked, embedded, and indexed alongside regular post text, making document contents fully searchable through AI semantic search and accessible to the AI chatbot. Ideal for forums with manuals, guides, reports, and technical documentation shared as attachments.', 'wpforo' ), |
| 1641 |
'plan' => 'professional', |
| 1642 |
'preview' => false, |
| 1643 |
], |
| 1644 |
'ai_bot_reply' => [ |
| 1645 |
'name' => __( 'AI Bot Reply and Reply Suggestion', 'wpforo' ), |
| 1646 |
'description' => __( 'Generate AI-powered replies manually with a single click or use the Suggest Reply button to get AI-generated content directly in the editor. Moderators can trigger bot replies from any post, or use the suggest feature to draft responses based on forum context, topic content, and AI knowledge base.', 'wpforo' ), |
| 1647 |
'plan' => 'professional', |
| 1648 |
'preview' => true, |
| 1649 |
], |
| 1650 |
'ai_topic_generator' => [ |
| 1651 |
'name' => __( 'AI Tasks - Automated Topic Generation', 'wpforo' ), |
| 1652 |
'description' => __( 'Keep your forum active with AI-generated topics! The AI analyzes your existing discussions and automatically creates engaging threads based on your instructions every day or in any time period you want. Topics appear naturally from AI created users or pre-defined users, sparking fresh conversations. The AI can search for trending news and current issues related to your community, then create timely, relevant topics that drive engagement.', 'wpforo' ), |
| 1653 |
'plan' => 'professional', |
| 1654 |
'preview' => true, |
| 1655 |
], |
| 1656 |
'ai_reply_generator' => [ |
| 1657 |
'name' => __( 'AI Tasks - Automated Reply Generation', 'wpforo' ), |
| 1658 |
'description' => __( 'Boost engagement with intelligent reply generation. AI monitors your forum for unanswered topics, analyzes context from existing discussions and knowledge base, and automatically posts helpful, relevant responses through bot users. Configure reply frequency, tone, and trigger conditions to maintain authentic community interaction.', 'wpforo' ), |
| 1659 |
'plan' => 'professional', |
| 1660 |
'preview' => true, |
| 1661 |
], |
| 1662 |
'auto_tag_generation' => [ |
| 1663 |
'name' => __( 'AI Tasks - Automated Topic Tag Moderation', 'wpforo' ), |
| 1664 |
'description' => __( 'Improve content discovery with smart tag management. Complete tag management powered by AI. Automatically generates relevant tags for new and existing topics, removes outdated or irrelevant tags, maintains consistent tag vocabulary, identifies duplicate tags, and suggests related keywords. Self-cleaning system ensures your tag structure stays organized as your forum evolves while leaving existing topics untouched to preserve forum integrity.', 'wpforo' ), |
| 1665 |
'plan' => 'professional', |
| 1666 |
'preview' => true, |
| 1667 |
], |
| 1668 |
'analytics_insights' => [ |
| 1669 |
'name' => __( 'AI Analytics & Insights', 'wpforo' ), |
| 1670 |
'description' => __( 'Stop guessing what your community wants. AI Analytics reveals hidden patterns in member behavior. Comprehensive AI-driven analytics for smarter community management. Monitor real-time engagement metrics, track topic performance, identify trending discussions, discover underserved content areas, and receive personalized growth recommendations. Advanced sentiment analysis, member retention insights, and predictive trends help you stay ahead.', 'wpforo' ), |
| 1671 |
'plan' => 'professional', |
| 1672 |
'preview' => true, |
| 1673 |
], |
| 1674 |
'ai_assistant_chatbot' => [ |
| 1675 |
'name' => __( 'AI Chat Assistant', 'wpforo' ), |
| 1676 |
'description' => __( '24/7 intelligent assistance for your forum members. Intelligent chatbot powered by your forum\'s content. Provides instant answers based on indexed discussions, suggests relevant topics, guides new members through common tasks, and escalates complex questions to moderators when needed. Learns from interactions, supports multiple languages, and maintains your community\'s tone and style.', 'wpforo' ), |
| 1677 |
'plan' => 'business', |
| 1678 |
'preview' => false, |
| 1679 |
], |
| 1680 |
'vector_db_cloud_storage' => [ |
| 1681 |
'name' => __( 'AI Indexed Vector Database - Cloud Storage', 'wpforo' ), |
| 1682 |
'description' => __( 'Scale your AI capabilities with cloud-based vector storage powered by AWS S3 Vectors. Ideal for large forums with thousands of posts and growing communities. Cloud storage provides unlimited scalability, faster query performance, automatic backups, and enterprise-grade reliability for your AI knowledge base.', 'wpforo' ), |
| 1683 |
'plan' => 'business', |
| 1684 |
'preview' => false, |
| 1685 |
], |
| 1686 |
'extended_knowledge_base' => [ |
| 1687 |
'name' => __( 'Extended Knowledge Base', 'wpforo' ), |
| 1688 |
'description' => __( 'Expand AI knowledge beyond forum content to include WordPress posts, pages, and products.', 'wpforo' ), |
| 1689 |
'plan' => 'business', |
| 1690 |
'preview' => false, |
| 1691 |
], |
| 1692 |
'wordpress_content_indexing' => [ |
| 1693 |
'name' => __( 'WordPress Content Indexing', 'wpforo' ), |
| 1694 |
'description' => __( 'Index WordPress posts and pages for comprehensive site-wide AI search.', 'wpforo' ), |
| 1695 |
'plan' => 'business', |
| 1696 |
'preview' => false, |
| 1697 |
], |
| 1698 |
'custom_post_types_indexing' => [ |
| 1699 |
'name' => __( 'Custom Post Types Indexing', 'wpforo' ), |
| 1700 |
'description' => __( 'Include custom post types in AI knowledge base for complete content coverage.', 'wpforo' ), |
| 1701 |
'plan' => 'business', |
| 1702 |
'preview' => false, |
| 1703 |
], |
| 1704 |
'woocommerce_products_indexing' => [ |
| 1705 |
'name' => __( 'WooCommerce Products Indexing', 'wpforo' ), |
| 1706 |
'description' => __( 'Index WooCommerce products to provide AI-powered product search and support.', 'wpforo' ), |
| 1707 |
'plan' => 'business', |
| 1708 |
'preview' => false, |
| 1709 |
], |
| 1710 |
'custom_knowledge_indexing' => [ |
| 1711 |
'name' => __( 'Custom Knowledge Indexing', 'wpforo' ), |
| 1712 |
'description' => __( 'Upload and index custom knowledge files (JSON, Markdown, Text) to enhance AI responses with your expert documentation, FAQs, and specialized content. Perfect for product manuals, internal guides, and domain-specific knowledge bases.', 'wpforo' ), |
| 1713 |
'plan' => 'business', |
| 1714 |
'preview' => false, |
| 1715 |
], |
| 1716 |
'file_indexing' => [ |
| 1717 |
'name' => __( 'File Indexing (TXT, MD, JSON, PDF)', 'wpforo' ), |
| 1718 |
'description' => __( 'Index plain text, Markdown, JSON, and PDF files into the AI knowledge base for richer answers from custom documentation and reference material. Scanned PDFs are auto-OCR\'d when the text layer is too sparse.', 'wpforo' ), |
| 1719 |
'plan' => 'business', |
| 1720 |
'preview' => false, |
| 1721 |
], |
| 1722 |
'developer_features' => [ |
| 1723 |
'name' => __( 'Developer Features', 'wpforo' ), |
| 1724 |
'description' => __( 'Advanced developer tools and API access for custom integrations.', 'wpforo' ), |
| 1725 |
'plan' => 'enterprise', |
| 1726 |
'preview' => false, |
| 1727 |
], |
| 1728 |
'rest_api_access' => [ |
| 1729 |
'name' => __( 'REST API Access', 'wpforo' ), |
| 1730 |
'description' => __( 'Full REST API access for custom applications and third-party integrations.', 'wpforo' ), |
| 1731 |
'plan' => 'enterprise', |
| 1732 |
'preview' => false, |
| 1733 |
], |
| 1734 |
'custom_ai_models' => [ |
| 1735 |
'name' => __( 'Custom AI Models', 'wpforo' ), |
| 1736 |
'description' => __( 'Use custom-trained AI models tailored to your specific community needs.', 'wpforo' ), |
| 1737 |
'plan' => 'enterprise', |
| 1738 |
'preview' => false, |
| 1739 |
], |
| 1740 |
'custom_feature_development' => [ |
| 1741 |
'name' => __( 'Custom feature development', 'wpforo' ), |
| 1742 |
'description' => __( 'Dedicated development resources for custom AI features unique to your forum.', 'wpforo' ), |
| 1743 |
'plan' => 'enterprise', |
| 1744 |
'preview' => false, |
| 1745 |
], |
| 1746 |
'premium_support' => [ |
| 1747 |
'name' => __( 'Premium Support', 'wpforo' ), |
| 1748 |
'description' => __( 'Priority support with dedicated account management and faster response times.', 'wpforo' ), |
| 1749 |
'plan' => 'enterprise', |
| 1750 |
'preview' => false, |
| 1751 |
], |
| 1752 |
'dedicated_account_manager' => [ |
| 1753 |
'name' => __( 'Dedicated account manager', 'wpforo' ), |
| 1754 |
'description' => __( 'Personal account manager for strategic guidance and priority assistance.', 'wpforo' ), |
| 1755 |
'plan' => 'enterprise', |
| 1756 |
'preview' => false, |
| 1757 |
], |
| 1758 |
'enterprise_capabilities' => [ |
| 1759 |
'name' => __( 'Enterprise Capabilities', 'wpforo' ), |
| 1760 |
'description' => __( 'Enterprise-grade features including SLA, compliance support, and advanced security.', 'wpforo' ), |
| 1761 |
'plan' => 'enterprise', |
| 1762 |
'preview' => false, |
| 1763 |
], |
| 1764 |
] ); |
| 1765 |
} |
| 1766 |
|
| 1767 |
/** |
| 1768 |
* Get SVG icon for a feature |
| 1769 |
* |
| 1770 |
* @param string $feature_id Feature identifier |
| 1771 |
* @return string SVG icon markup |
| 1772 |
*/ |
| 1773 |
function wpforo_ai_get_feature_icon( $feature_id ) { |
| 1774 |
$icons = [ |
| 1775 |
// Free Features - Vector Database Storage |
| 1776 |
'vector_db_local_storage' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4 3 9 3s9-1.34 9-3"/><path d="M12 12v5"/><path d="M9 14.5l3 2.5 3-2.5"/></svg>', |
| 1777 |
'vector_db_cloud_storage' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"/><path d="M12 13v5"/><path d="M9.5 15.5l2.5 2.5 2.5-2.5"/></svg>', |
| 1778 |
// Starter Features |
| 1779 |
'semantic_search' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/><path d="M11 8a3 3 0 0 0-3 3"/></svg>', |
| 1780 |
'content_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4 3 9 3s9-1.34 9-3"/></svg>', |
| 1781 |
'image_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>', |
| 1782 |
'document_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>', |
| 1783 |
'multi_language_translation' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>', |
| 1784 |
'topic_summary' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72Z"/><path d="m14 7 3 3"/><path d="M5 6v4"/><path d="M19 14v4"/><path d="M10 2v2"/><path d="M7 8H3"/><path d="M21 16h-4"/><path d="M11 3H9"/></svg>', |
| 1785 |
'smart_topic_suggestions' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/></svg>', |
| 1786 |
'topic_suggestions' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/></svg>', |
| 1787 |
'ai_topic_generator' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.375 2.625a2.121 2.121 0 1 1 3 3L12 15l-4 1 1-4Z"/></svg>', |
| 1788 |
'ai_reply_generator' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/><path d="M8 10h8"/><path d="M8 14h4"/></svg>', |
| 1789 |
'ai_bot_reply' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="10" x="3" y="11" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4"/><path d="M8 16h0"/><path d="M16 16h0"/><path d="m2 2 2 2"/><path d="m22 2-2 2"/></svg>', |
| 1790 |
'forum_image_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/><path d="M14 3v4"/><path d="M21 10h-4"/></svg>', |
| 1791 |
'forum_document_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/><path d="M14 2v4"/><path d="M20 9h-4"/></svg>', |
| 1792 |
'automatic_faq_generation' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>', |
| 1793 |
'auto_tag_generation' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"/><circle cx="7.5" cy="7.5" r="1.5"/></svg>', |
| 1794 |
'analytics_insights' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><path d="m19 9-5 5-4-4-3 3"/></svg>', |
| 1795 |
// Professional Features - Content Moderation |
| 1796 |
'ai_spam_detection' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="m9 12 2 2 4-4"/></svg>', |
| 1797 |
'ai_toxicity_detection' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/></svg>', |
| 1798 |
'ai_rule_compliance' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="m9 15 2 2 4-4"/></svg>', |
| 1799 |
'unified_moderation' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><path d="m9 12 2 2 4-4"/></svg>', |
| 1800 |
'ai_assistant_chatbot' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="10" x="3" y="11" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4"/><path d="M8 16h0"/><path d="M16 16h0"/></svg>', |
| 1801 |
// Business Features |
| 1802 |
'extended_knowledge_base' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/><path d="M8 7h6"/><path d="M8 11h8"/></svg>', |
| 1803 |
'wordpress_content_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/></svg>', |
| 1804 |
'custom_post_types_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"/><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"/><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"/></svg>', |
| 1805 |
'woocommerce_products_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="8" cy="21" r="1"/><circle cx="19" cy="21" r="1"/><path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"/></svg>', |
| 1806 |
'custom_knowledge_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"/><path d="M8 11h8"/><path d="M8 7h6"/><circle cx="12" cy="15" r="1"/></svg>', |
| 1807 |
'file_indexing' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="M8 13h8"/><path d="M8 17h5"/></svg>', |
| 1808 |
// Enterprise Features |
| 1809 |
'developer_features' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>', |
| 1810 |
'rest_api_access' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 20V10"/><path d="M12 20V4"/><path d="M6 20v-6"/><circle cx="18" cy="7" r="3"/><circle cx="6" cy="11" r="3"/></svg>', |
| 1811 |
'custom_ai_models' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a4 4 0 0 0-4 4v2H6a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V10a2 2 0 0 0-2-2h-2V6a4 4 0 0 0-4-4z"/><circle cx="12" cy="14" r="2"/><path d="M12 16v2"/></svg>', |
| 1812 |
'custom_feature_development' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>', |
| 1813 |
'premium_support' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 11h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Zm0 0a9 9 0 1 1 18 0m0 0v5a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3Z"/></svg>', |
| 1814 |
'dedicated_account_manager' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>', |
| 1815 |
'enterprise_capabilities' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect width="16" height="20" x="4" y="2" rx="2" ry="2"/><path d="M9 22v-4h6v4"/><path d="M8 6h.01"/><path d="M16 6h.01"/><path d="M12 6h.01"/><path d="M12 10h.01"/><path d="M12 14h.01"/><path d="M16 10h.01"/><path d="M16 14h.01"/><path d="M8 10h.01"/><path d="M8 14h.01"/></svg>', |
| 1816 |
]; |
| 1817 |
|
| 1818 |
// Return the icon or a default one |
| 1819 |
if ( isset( $icons[ $feature_id ] ) ) { |
| 1820 |
return $icons[ $feature_id ]; |
| 1821 |
} |
| 1822 |
|
| 1823 |
// Default icon (star) |
| 1824 |
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>'; |
| 1825 |
} |
| 1826 |
|
| 1827 |
/** |
| 1828 |
* Render usage statistics |
| 1829 |
* |
| 1830 |
* @param array $usage Usage data (since last credit purchase) |
| 1831 |
* @param int $total_credits Total credits used |
| 1832 |
* @param array $usage_lifetime Lifetime usage data (optional) |
| 1833 |
* @param string $current_plan Current subscription plan (optional) |
| 1834 |
*/ |
| 1835 |
function wpforo_ai_render_usage_stats( $usage, $total_credits, $usage_lifetime = [], $current_plan = 'free_trial' ) { |
| 1836 |
// Ensure $total_credits is an integer |
| 1837 |
$total_credits = (int) $total_credits; |
| 1838 |
|
| 1839 |
$features = wpforo_ai_get_all_features(); |
| 1840 |
$has_lifetime = ! empty( $usage_lifetime ); |
| 1841 |
|
| 1842 |
echo '<div class="wpforo-ai-usage-stats">'; |
| 1843 |
echo '<div class="usage-summary">'; |
| 1844 |
echo '<div class="usage-stat-item">'; |
| 1845 |
echo '<span class="stat-icon dashicons dashicons-chart-bar"></span>'; |
| 1846 |
echo '<div class="stat-info">'; |
| 1847 |
echo '<strong>' . number_format( $total_credits ) . '</strong>'; |
| 1848 |
echo '<span class="stat-label">' . __( 'Lifetime Credits Used', 'wpforo' ) . '</span>'; |
| 1849 |
echo '</div>'; |
| 1850 |
echo '</div>'; |
| 1851 |
echo '</div>'; |
| 1852 |
|
| 1853 |
echo '<table class="wpforo-ai-usage-table">'; |
| 1854 |
echo '<thead>'; |
| 1855 |
echo '<tr>'; |
| 1856 |
echo '<th>' . __( 'Feature', 'wpforo' ) . '</th>'; |
| 1857 |
echo '<th>' . __( 'Since Last Purchase', 'wpforo' ) . '</th>'; |
| 1858 |
if ( $has_lifetime ) { |
| 1859 |
echo '<th>' . __( 'Lifetime Total', 'wpforo' ) . '</th>'; |
| 1860 |
} |
| 1861 |
echo '</tr>'; |
| 1862 |
echo '</thead>'; |
| 1863 |
echo '<tbody>'; |
| 1864 |
|
| 1865 |
// Get all features available for the current plan |
| 1866 |
$plan_features = []; |
| 1867 |
// Skip storage features and sub-indexing features (their credits are summed into content_indexing) |
| 1868 |
$skip_features = [ 'vector_db_local_storage', 'vector_db_cloud_storage', 'forum_image_indexing', 'forum_document_indexing' ]; |
| 1869 |
foreach ( $features as $feature_id => $feature_data ) { |
| 1870 |
// Skip storage features from usage statistics |
| 1871 |
if ( in_array( $feature_id, $skip_features, true ) ) { |
| 1872 |
continue; |
| 1873 |
} |
| 1874 |
|
| 1875 |
$feature_plan = isset( $feature_data['plan'] ) ? $feature_data['plan'] : 'starter'; |
| 1876 |
$feature_status = isset( $feature_data['status'] ) ? $feature_data['status'] : 'available'; |
| 1877 |
|
| 1878 |
// Only include features that are enabled for this plan and not "coming soon" |
| 1879 |
if ( wpforo_ai_is_feature_enabled_by_plan( $current_plan, $feature_plan ) && $feature_status !== 'coming_soon' ) { |
| 1880 |
$plan_features[] = $feature_id; |
| 1881 |
} |
| 1882 |
} |
| 1883 |
|
| 1884 |
// If no plan features found, fall back to usage keys |
| 1885 |
if ( empty( $plan_features ) ) { |
| 1886 |
$plan_features = $has_lifetime ? array_keys( $usage_lifetime ) : array_keys( $usage ); |
| 1887 |
} |
| 1888 |
|
| 1889 |
foreach ( $plan_features as $feature_id ) { |
| 1890 |
$feature_name = ''; |
| 1891 |
if ( isset( $features[ $feature_id ]['name'] ) ) { |
| 1892 |
$feature_name = $features[ $feature_id ]['name']; |
| 1893 |
} |
| 1894 |
if ( ! $feature_name ) { |
| 1895 |
$feature_name = ucwords( str_replace( '_', ' ', $feature_id ) ); |
| 1896 |
} |
| 1897 |
|
| 1898 |
// Get counts (since last purchase and lifetime) |
| 1899 |
$count_since_purchase = isset( $usage[ $feature_id ] ) ? (int) $usage[ $feature_id ] : 0; |
| 1900 |
$count_lifetime = $has_lifetime && isset( $usage_lifetime[ $feature_id ] ) ? (int) $usage_lifetime[ $feature_id ] : 0; |
| 1901 |
|
| 1902 |
// For content_indexing, include image and document indexing credits |
| 1903 |
if ( 'content_indexing' === $feature_id ) { |
| 1904 |
$count_since_purchase += ( isset( $usage['multimodal_image_indexing'] ) ? (int) $usage['multimodal_image_indexing'] : 0 ); |
| 1905 |
$count_since_purchase += ( isset( $usage['document_indexing'] ) ? (int) $usage['document_indexing'] : 0 ); |
| 1906 |
if ( $has_lifetime ) { |
| 1907 |
$count_lifetime += ( isset( $usage_lifetime['multimodal_image_indexing'] ) ? (int) $usage_lifetime['multimodal_image_indexing'] : 0 ); |
| 1908 |
$count_lifetime += ( isset( $usage_lifetime['document_indexing'] ) ? (int) $usage_lifetime['document_indexing'] : 0 ); |
| 1909 |
} |
| 1910 |
} |
| 1911 |
|
| 1912 |
echo '<tr>'; |
| 1913 |
echo '<td>' . esc_html( $feature_name ) . '</td>'; |
| 1914 |
echo '<td><strong>' . number_format( $count_since_purchase ) . '</strong></td>'; |
| 1915 |
if ( $has_lifetime ) { |
| 1916 |
echo '<td><strong>' . number_format( $count_lifetime ) . '</strong></td>'; |
| 1917 |
} |
| 1918 |
echo '</tr>'; |
| 1919 |
} |
| 1920 |
|
| 1921 |
echo '</tbody>'; |
| 1922 |
echo '</table>'; |
| 1923 |
echo '</div>'; |
| 1924 |
} |
| 1925 |
|
| 1926 |
/** |
| 1927 |
* Render pricing table |
| 1928 |
* |
| 1929 |
* @param string $tenant_id Tenant ID for upgrade URLs |
| 1930 |
* @param array $subscription Current subscription data (optional, for showing active plan) |
| 1931 |
*/ |
| 1932 |
function wpforo_ai_render_pricing_table( $tenant_id, $subscription = [] ) { |
| 1933 |
// Get current plan and expiration date |
| 1934 |
$current_plan = isset( $subscription['plan'] ) ? $subscription['plan'] : 'free_trial'; |
| 1935 |
$renews_at = isset( $subscription['renews_at'] ) ? $subscription['renews_at'] : ''; |
| 1936 |
$expires_at = isset( $subscription['expires_at'] ) ? $subscription['expires_at'] : ''; |
| 1937 |
|
| 1938 |
// Plan hierarchy for disabling lower plan buttons |
| 1939 |
$plan_levels = [ |
| 1940 |
'free_trial' => 0, |
| 1941 |
'free' => 0, |
| 1942 |
'starter' => 1, |
| 1943 |
'professional' => 2, |
| 1944 |
'business' => 3, |
| 1945 |
'enterprise' => 4, |
| 1946 |
]; |
| 1947 |
$current_level = isset( $plan_levels[ $current_plan ] ) ? $plan_levels[ $current_plan ] : 0; |
| 1948 |
|
| 1949 |
// Fetch dynamic pricing from Freemius API (with fallback to defaults) |
| 1950 |
$pricing = wpforo_ai_get_freemius_pricing(); |
| 1951 |
$plans = $pricing['plans']; |
| 1952 |
|
| 1953 |
?> |
| 1954 |
<div class="wpforo-ai-callout" style="display: none;"> |
| 1955 |
<span class="dashicons dashicons-info"></span> |
| 1956 |
<div> |
| 1957 |
<strong><?php _e( 'Credit-Based Pricing', 'wpforo' ); ?></strong> |
| 1958 |
<p><?php _e( 'Pay only for what you use with flexible credit-based pricing. Credits roll over month-to-month as long as you have an active subscription plan. Each plan allows credit accumulation up to one year of subscription plan credits. Start with 500 free credits, then choose a plan that fits your forum\'s activity level.', 'wpforo' ); ?><br><?php _e('You can select the quality of AI model for each feature individually: ', 'wpforo') ?></p> |
| 1959 |
<ul style="list-style: square; padding: 0 18px; margin: 5px 0 0 0;"> |
| 1960 |
<li style="margin-bottom: 1px;"><?php _e( 'Fast (1 action = 1 credit)', 'wpforo' ); ?></li> |
| 1961 |
<li style="margin-bottom: 1px;"><?php _e( 'Balanced (1 action = 2 credits)', 'wpforo' ); ?></li> |
| 1962 |
<li style="margin-bottom: 1px;"><?php _e( 'Advanced (1 action = 3 credits)', 'wpforo' ); ?></li> |
| 1963 |
<li style="margin-bottom: 1px;"><?php _e( 'Premium (1 action = 4 credits)', 'wpforo' ); ?></li> |
| 1964 |
</ul> |
| 1965 |
</div> |
| 1966 |
</div> |
| 1967 |
<div class="wpforo-ai-pricing-table"> |
| 1968 |
<table class="pricing-table-modern"> |
| 1969 |
<thead> |
| 1970 |
<tr> |
| 1971 |
<th class="feature-column"><?php _e( 'AI Features', 'wpforo' ); ?></th> |
| 1972 |
<th class="plan-column plan-starter <?php echo $current_plan === 'starter' ? 'plan-active' : ''; ?>"> |
| 1973 |
<div class="plan-header"> |
| 1974 |
<?php if ( $current_plan === 'starter' ) : ?> |
| 1975 |
<div class="plan-active-badge"><?php _e( 'YOUR PLAN', 'wpforo' ); ?></div> |
| 1976 |
<?php endif; ?> |
| 1977 |
<div class="plan-name"><?php _e( 'Starter', 'wpforo' ); ?></div> |
| 1978 |
<div class="plan-price"> |
| 1979 |
<span class="currency">$</span><span class="price-amount"><?php echo esc_html( $plans['starter']['price'] ); ?></span><small class="billing-period">/month</small> |
| 1980 |
</div> |
| 1981 |
<div class="plan-credits"> |
| 1982 |
<span class="dashicons dashicons-awards"></span> |
| 1983 |
<strong>+1,000</strong> <?php _e( 'credits', 'wpforo' ); ?> |
| 1984 |
</div> |
| 1985 |
</div> |
| 1986 |
</th> |
| 1987 |
<th class="plan-column plan-professional <?php echo $current_plan === 'professional' ? 'plan-active' : ''; ?>"> |
| 1988 |
<div class="plan-header"> |
| 1989 |
<?php if ( $current_plan === 'professional' ) : ?> |
| 1990 |
<div class="plan-active-badge"><?php _e( 'YOUR PLAN', 'wpforo' ); ?></div> |
| 1991 |
<?php else : ?> |
| 1992 |
<div class="plan-popular-badge"><?php _e( 'POPULAR', 'wpforo' ); ?></div> |
| 1993 |
<?php endif; ?> |
| 1994 |
<div class="plan-name"><?php _e( 'Professional', 'wpforo' ); ?></div> |
| 1995 |
<div class="plan-price"> |
| 1996 |
<span class="currency">$</span><span class="price-amount"><?php echo esc_html( $plans['professional']['price'] ); ?></span><small class="billing-period">/month</small> |
| 1997 |
</div> |
| 1998 |
<div class="plan-credits"> |
| 1999 |
<span class="dashicons dashicons-awards"></span> |
| 2000 |
<strong>+3,000</strong> <?php _e( 'credits', 'wpforo' ); ?> |
| 2001 |
</div> |
| 2002 |
</div> |
| 2003 |
</th> |
| 2004 |
<th class="plan-column plan-business <?php echo $current_plan === 'business' ? 'plan-active' : ''; ?>"> |
| 2005 |
<div class="plan-header"> |
| 2006 |
<?php if ( $current_plan === 'business' ) : ?> |
| 2007 |
<div class="plan-active-badge"><?php _e( 'YOUR PLAN', 'wpforo' ); ?></div> |
| 2008 |
<?php endif; ?> |
| 2009 |
<div class="plan-name"><?php _e( 'Business', 'wpforo' ); ?></div> |
| 2010 |
<div class="plan-price"> |
| 2011 |
<span class="currency">$</span><span class="price-amount"><?php echo esc_html( $plans['business']['price'] ); ?></span><small class="billing-period">/month</small> |
| 2012 |
</div> |
| 2013 |
<div class="plan-credits"> |
| 2014 |
<span class="dashicons dashicons-awards"></span> |
| 2015 |
<strong>+9,000</strong> <?php _e( 'credits', 'wpforo' ); ?> |
| 2016 |
</div> |
| 2017 |
</div> |
| 2018 |
</th> |
| 2019 |
<th class="plan-column plan-enterprise <?php echo $current_plan === 'enterprise' ? 'plan-active' : ''; ?>"> |
| 2020 |
<div class="plan-header"> |
| 2021 |
<?php if ( $current_plan === 'enterprise' ) : ?> |
| 2022 |
<div class="plan-active-badge"><?php _e( 'YOUR PLAN', 'wpforo' ); ?></div> |
| 2023 |
<?php endif; ?> |
| 2024 |
<div class="plan-name"><?php _e( 'Enterprise', 'wpforo' ); ?></div> |
| 2025 |
<div class="plan-price"> |
| 2026 |
<span class="price-amount" style="font-weight: 400; font-size: 16px;"><?php _e( 'Custom Price', 'wpforo' ); ?></span> |
| 2027 |
</div> |
| 2028 |
<div class="plan-credits"> |
| 2029 |
<span class="dashicons dashicons-awards"></span> |
| 2030 |
<strong style="font-weight: 500;"><?php _e( 'Custom', 'wpforo' ); ?></strong> <?php _e( 'credits', 'wpforo' ); ?> |
| 2031 |
</div> |
| 2032 |
</div> |
| 2033 |
</th> |
| 2034 |
</tr> |
| 2035 |
</thead> |
| 2036 |
<tbody> |
| 2037 |
<!-- CTA Row --> |
| 2038 |
<tr class="cta-row"> |
| 2039 |
<td></td> |
| 2040 |
<td> |
| 2041 |
<?php if ( $current_plan === 'starter' ) : ?> |
| 2042 |
<div class="plan-active-info"> |
| 2043 |
<span class="dashicons dashicons-yes-alt"></span> |
| 2044 |
<strong><?php _e( 'Active', 'wpforo' ); ?></strong> |
| 2045 |
<?php if ( $renews_at ) : ?> |
| 2046 |
<small><?php printf( __( 'Renews %s', 'wpforo' ), esc_html( wpforo_ai_format_date( $renews_at ) ) ); ?></small> |
| 2047 |
<?php endif; ?> |
| 2048 |
</div> |
| 2049 |
<?php elseif ( $plan_levels['starter'] < $current_level ) : ?> |
| 2050 |
<button type="button" class="button button-secondary button-cta" disabled> |
| 2051 |
<?php _e( 'Upgrade', 'wpforo' ); ?> |
| 2052 |
</button> |
| 2053 |
<?php else : ?> |
| 2054 |
<button type="button" class="button button-secondary button-cta wpforo-ai-upgrade-btn" data-plan="starter" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2055 |
<?php $current_plan === 'free_trial' ? _e( 'Get Started', 'wpforo' ) : _e( 'Upgrade', 'wpforo' ); ?> |
| 2056 |
</button> |
| 2057 |
<?php endif; ?> |
| 2058 |
</td> |
| 2059 |
<td> |
| 2060 |
<?php if ( $current_plan === 'professional' ) : ?> |
| 2061 |
<div class="plan-active-info"> |
| 2062 |
<!-- <span class="dashicons dashicons-yes-alt"></span> --> |
| 2063 |
<strong><?php _e( 'Active', 'wpforo' ); ?></strong> |
| 2064 |
<?php if ( $renews_at ) : ?> |
| 2065 |
<small><?php printf( __( 'Renews %s', 'wpforo' ), esc_html( wpforo_ai_format_date( $renews_at ) ) ); ?></small> |
| 2066 |
<?php endif; ?> |
| 2067 |
</div> |
| 2068 |
<?php elseif ( $plan_levels['professional'] < $current_level ) : ?> |
| 2069 |
<button type="button" class="button button-secondary button-cta" disabled> |
| 2070 |
<?php _e( 'Upgrade', 'wpforo' ); ?> |
| 2071 |
</button> |
| 2072 |
<?php else : ?> |
| 2073 |
<button type="button" class="button button-secondary button-cta wpforo-ai-upgrade-btn" data-plan="professional" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2074 |
<?php $current_plan === 'free_trial' ? _e( 'Get Started', 'wpforo' ) : _e( 'Upgrade', 'wpforo' ); ?> |
| 2075 |
</button> |
| 2076 |
<?php endif; ?> |
| 2077 |
</td> |
| 2078 |
<td> |
| 2079 |
<?php if ( $current_plan === 'business' ) : ?> |
| 2080 |
<div class="plan-active-info"> |
| 2081 |
<!-- <span class="dashicons dashicons-yes-alt"></span> --> |
| 2082 |
<strong><?php _e( 'Active', 'wpforo' ); ?></strong> |
| 2083 |
<?php if ( $renews_at ) : ?> |
| 2084 |
<small><?php printf( __( 'Renews %s', 'wpforo' ), esc_html( wpforo_ai_format_date( $renews_at ) ) ); ?></small> |
| 2085 |
<?php endif; ?> |
| 2086 |
</div> |
| 2087 |
<?php elseif ( $plan_levels['business'] < $current_level ) : ?> |
| 2088 |
<button type="button" class="button button-secondary button-cta" disabled> |
| 2089 |
<?php _e( 'Upgrade', 'wpforo' ); ?> |
| 2090 |
</button> |
| 2091 |
<?php else : ?> |
| 2092 |
<button type="button" class="button button-secondary button-cta wpforo-ai-upgrade-btn" data-plan="business" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2093 |
<?php $current_plan === 'free_trial' ? _e( 'Get Started', 'wpforo' ) : _e( 'Upgrade', 'wpforo' ); ?> |
| 2094 |
</button> |
| 2095 |
<?php endif; ?> |
| 2096 |
</td> |
| 2097 |
<td> |
| 2098 |
<?php if ( $current_plan === 'enterprise' ) : ?> |
| 2099 |
<div class="plan-active-info"> |
| 2100 |
<!-- <span class="dashicons dashicons-yes-alt"></span> --> |
| 2101 |
<strong><?php _e( 'Active', 'wpforo' ); ?></strong> |
| 2102 |
<?php if ( $renews_at ) : ?> |
| 2103 |
<small><?php printf( __( 'Renews %s', 'wpforo' ), esc_html( wpforo_ai_format_date( $renews_at ) ) ); ?></small> |
| 2104 |
<?php endif; ?> |
| 2105 |
</div> |
| 2106 |
<?php else : ?> |
| 2107 |
<a href="https://wpforo.com/gvectors-ai/#gvai-contact" target="_blank" class="button button-secondary" style="padding: 5px 20px;"> |
| 2108 |
<?php _e( 'Contact Us', 'wpforo' ) ?> |
| 2109 |
</a> |
| 2110 |
<?php endif; ?> |
| 2111 |
</td> |
| 2112 |
</tr> |
| 2113 |
|
| 2114 |
<!-- Core Features --> |
| 2115 |
<tr class="feature-category"> |
| 2116 |
<td colspan="5"><span class="dashicons dashicons-yes-alt"></span> <?php _e( 'ALL Core AI Features', 'wpforo' ); ?></td> |
| 2117 |
</tr> |
| 2118 |
<tr> |
| 2119 |
<td><?php _e( 'AI Knowledge - Content Text Indexing', 'wpforo' ); ?></td> |
| 2120 |
<td><span class="checkmark">✓</span></td> |
| 2121 |
<td><span class="checkmark">✓</span></td> |
| 2122 |
<td><span class="checkmark">✓</span></td> |
| 2123 |
<td><span class="checkmark">✓</span></td> |
| 2124 |
</tr> |
| 2125 |
<tr> |
| 2126 |
<td><?php _e( 'AI Vector Database - Local Storage', 'wpforo' ); ?></td> |
| 2127 |
<td><span class="checkmark">✓</span></td> |
| 2128 |
<td><span class="checkmark">✓</span></td> |
| 2129 |
<td><span class="checkmark">✓</span></td> |
| 2130 |
<td><span class="checkmark">✓</span></td> |
| 2131 |
</tr> |
| 2132 |
<tr> |
| 2133 |
<td><?php _e( 'AI Semantic Search', 'wpforo' ); ?></td> |
| 2134 |
<td><span class="checkmark">✓</span></td> |
| 2135 |
<td><span class="checkmark">✓</span></td> |
| 2136 |
<td><span class="checkmark">✓</span></td> |
| 2137 |
<td><span class="checkmark">✓</span></td> |
| 2138 |
</tr> |
| 2139 |
<tr> |
| 2140 |
<td><?php _e( 'AI Search Enhancement', 'wpforo' ); ?></td> |
| 2141 |
<td><span class="checkmark">✓</span></td> |
| 2142 |
<td><span class="checkmark">✓</span></td> |
| 2143 |
<td><span class="checkmark">✓</span></td> |
| 2144 |
<td><span class="checkmark">✓</span></td> |
| 2145 |
</tr> |
| 2146 |
<tr> |
| 2147 |
<td><?php _e( 'AI Topic Summarization', 'wpforo' ); ?></td> |
| 2148 |
<td><span class="checkmark">✓</span></td> |
| 2149 |
<td><span class="checkmark">✓</span></td> |
| 2150 |
<td><span class="checkmark">✓</span></td> |
| 2151 |
<td><span class="checkmark">✓</span></td> |
| 2152 |
</tr> |
| 2153 |
<tr> |
| 2154 |
<td><?php _e( 'AI Topic Suggestions', 'wpforo' ); ?></td> |
| 2155 |
<td><span class="checkmark">✓</span></td> |
| 2156 |
<td><span class="checkmark">✓</span></td> |
| 2157 |
<td><span class="checkmark">✓</span></td> |
| 2158 |
<td><span class="checkmark">✓</span></td> |
| 2159 |
</tr> |
| 2160 |
<tr> |
| 2161 |
<td><?php _e( 'AI Multi-Language Translation', 'wpforo' ); ?></td> |
| 2162 |
<td><span class="checkmark">✓</span></td> |
| 2163 |
<td><span class="checkmark">✓</span></td> |
| 2164 |
<td><span class="checkmark">✓</span></td> |
| 2165 |
<td><span class="checkmark">✓</span></td> |
| 2166 |
</tr> |
| 2167 |
<tr> |
| 2168 |
<td><strong><?php _e( 'AI Auto Moderation', 'wpforo' ); ?></strong></td> |
| 2169 |
<td><span class="checkmark">✓</span></td> |
| 2170 |
<td><span class="checkmark">✓</span></td> |
| 2171 |
<td><span class="checkmark">✓</span></td> |
| 2172 |
<td><span class="checkmark">✓</span></td> |
| 2173 |
</tr> |
| 2174 |
<tr class="feature-item"> |
| 2175 |
<td><?php _e( 'Spam Detection and User Banning', 'wpforo' ); ?></td> |
| 2176 |
<td><span class="checkmark">✓</span></td> |
| 2177 |
<td><span class="checkmark">✓</span></td> |
| 2178 |
<td><span class="checkmark">✓</span></td> |
| 2179 |
<td><span class="checkmark">✓</span></td> |
| 2180 |
</tr> |
| 2181 |
<tr class="feature-item"> |
| 2182 |
<td><?php _e( 'Content Safety & Toxicity Detection', 'wpforo' ); ?></td> |
| 2183 |
<td><span class="checkmark">✓</span></td> |
| 2184 |
<td><span class="checkmark">✓</span></td> |
| 2185 |
<td><span class="checkmark">✓</span></td> |
| 2186 |
<td><span class="checkmark">✓</span></td> |
| 2187 |
</tr> |
| 2188 |
<tr class="feature-item"> |
| 2189 |
<td><?php _e( 'Rule Compliance & Policy Enforcement', 'wpforo' ); ?></td> |
| 2190 |
<td><span class="checkmark">✓</span></td> |
| 2191 |
<td><span class="checkmark">✓</span></td> |
| 2192 |
<td><span class="checkmark">✓</span></td> |
| 2193 |
<td><span class="checkmark">✓</span></td> |
| 2194 |
</tr> |
| 2195 |
<!-- Professional Features --> |
| 2196 |
<tr class="feature-category"> |
| 2197 |
<td colspan="5"><span class="dashicons dashicons-shield-alt"></span> <?php _e( 'Professional Features', 'wpforo' ); ?></td> |
| 2198 |
</tr> |
| 2199 |
|
| 2200 |
<tr> |
| 2201 |
<td><?php _e( 'AI Knowledge - Image Indexing', 'wpforo' ); ?></td> |
| 2202 |
<td><span class="crossmark">✗</span></td> |
| 2203 |
<td><span class="checkmark">✓</span></td> |
| 2204 |
<td><span class="checkmark">✓</span></td> |
| 2205 |
<td><span class="checkmark">✓</span></td> |
| 2206 |
</tr> |
| 2207 |
<tr> |
| 2208 |
<td><?php _e( 'AI Knowledge - Document Indexing', 'wpforo' ); ?></td> |
| 2209 |
<td><span class="crossmark">✗</span></td> |
| 2210 |
<td><span class="checkmark">✓</span></td> |
| 2211 |
<td><span class="checkmark">✓</span></td> |
| 2212 |
<td><span class="checkmark">✓</span></td> |
| 2213 |
</tr> |
| 2214 |
<tr> |
| 2215 |
<td><?php _e( 'AI Bot Reply', 'wpforo' ); ?></td> |
| 2216 |
<td><span class="crossmark">✗</span></td> |
| 2217 |
<td><span class="checkmark">✓</span></td> |
| 2218 |
<td><span class="checkmark">✓</span></td> |
| 2219 |
<td><span class="checkmark">✓</span></td> |
| 2220 |
</tr> |
| 2221 |
<tr> |
| 2222 |
<td><?php _e( 'AI Reply Suggestion', 'wpforo' ); ?></td> |
| 2223 |
<td><span class="crossmark">✗</span></td> |
| 2224 |
<td><span class="checkmark">✓</span></td> |
| 2225 |
<td><span class="checkmark">✓</span></td> |
| 2226 |
<td><span class="checkmark">✓</span></td> |
| 2227 |
</tr> |
| 2228 |
<tr> |
| 2229 |
<td><strong><?php _e( 'AI Tasks and Automations', 'wpforo' ); ?></strong></td> |
| 2230 |
<td><span class="crossmark">✗</span></td> |
| 2231 |
<td><span class="checkmark">✓</span></td> |
| 2232 |
<td><span class="checkmark">✓</span></td> |
| 2233 |
<td><span class="checkmark">✓</span></td> |
| 2234 |
</tr> |
| 2235 |
<tr class="feature-item"> |
| 2236 |
<td><?php _e( 'New Topic Creation', 'wpforo' ); ?></td> |
| 2237 |
<td><span class="crossmark">✗</span></td> |
| 2238 |
<td><span class="checkmark">✓</span></td> |
| 2239 |
<td><span class="checkmark">✓</span></td> |
| 2240 |
<td><span class="checkmark">✓</span></td> |
| 2241 |
</tr> |
| 2242 |
<tr class="feature-item"> |
| 2243 |
<td><?php _e( 'Auto Reply to Topics', 'wpforo' ); ?></td> |
| 2244 |
<td><span class="crossmark">✗</span></td> |
| 2245 |
<td><span class="checkmark">✓</span></td> |
| 2246 |
<td><span class="checkmark">✓</span></td> |
| 2247 |
<td><span class="checkmark">✓</span></td> |
| 2248 |
</tr> |
| 2249 |
<tr class="feature-item"> |
| 2250 |
<td><?php _e( 'Topic Tag Moderation', 'wpforo' ); ?></td> |
| 2251 |
<td><span class="crossmark">✗</span></td> |
| 2252 |
<td><span class="checkmark">✓</span></td> |
| 2253 |
<td><span class="checkmark">✓</span></td> |
| 2254 |
<td><span class="checkmark">✓</span></td> |
| 2255 |
</tr> |
| 2256 |
<tr> |
| 2257 |
<td><strong><?php _e( 'AI Analytics & Insights', 'wpforo' ); ?></strong></td> |
| 2258 |
<td><span class="crossmark">✗</span></td> |
| 2259 |
<td><span class="checkmark">✓</span></td> |
| 2260 |
<td><span class="checkmark">✓</span></td> |
| 2261 |
<td><span class="checkmark">✓</span></td> |
| 2262 |
</tr> |
| 2263 |
<tr class="feature-item"> |
| 2264 |
<td><?php _e( 'AI Insights', 'wpforo' ); ?></td> |
| 2265 |
<td><span class="crossmark">✗</span></td> |
| 2266 |
<td><span class="checkmark">✓</span></td> |
| 2267 |
<td><span class="checkmark">✓</span></td> |
| 2268 |
<td><span class="checkmark">✓</span></td> |
| 2269 |
</tr> |
| 2270 |
<tr class="feature-item"> |
| 2271 |
<td><?php _e( 'AI Usage Analytics', 'wpforo' ); ?></td> |
| 2272 |
<td><span class="crossmark">✗</span></td> |
| 2273 |
<td><span class="checkmark">✓</span></td> |
| 2274 |
<td><span class="checkmark">✓</span></td> |
| 2275 |
<td><span class="checkmark">✓</span></td> |
| 2276 |
</tr> |
| 2277 |
<tr class="feature-item"> |
| 2278 |
<td><?php _e( 'Forum Activity', 'wpforo' ); ?></td> |
| 2279 |
<td><span class="crossmark">✗</span></td> |
| 2280 |
<td><span class="checkmark">✓</span></td> |
| 2281 |
<td><span class="checkmark">✓</span></td> |
| 2282 |
<td><span class="checkmark">✓</span></td> |
| 2283 |
</tr> |
| 2284 |
<tr class="feature-item"> |
| 2285 |
<td><?php _e( 'User Engagement', 'wpforo' ); ?></td> |
| 2286 |
<td><span class="crossmark">✗</span></td> |
| 2287 |
<td><span class="checkmark">✓</span></td> |
| 2288 |
<td><span class="checkmark">✓</span></td> |
| 2289 |
<td><span class="checkmark">✓</span></td> |
| 2290 |
</tr> |
| 2291 |
<tr class="feature-item"> |
| 2292 |
<td><?php _e( 'Content Performance', 'wpforo' ); ?></td> |
| 2293 |
<td><span class="crossmark">✗</span></td> |
| 2294 |
<td><span class="checkmark">✓</span></td> |
| 2295 |
<td><span class="checkmark">✓</span></td> |
| 2296 |
<td><span class="checkmark">✓</span></td> |
| 2297 |
</tr> |
| 2298 |
|
| 2299 |
|
| 2300 |
<!-- Business Features --> |
| 2301 |
<tr class="feature-category"> |
| 2302 |
<td colspan="5"><span class="dashicons dashicons-portfolio"></span> <?php _e( 'Business Features', 'wpforo' ); ?></td> |
| 2303 |
</tr> |
| 2304 |
<tr> |
| 2305 |
<td><?php _e( 'AI Chat Assistant', 'wpforo' ); ?></td> |
| 2306 |
<td><span class="crossmark">✗</span></td> |
| 2307 |
<td><span class="crossmark">✗</span></td> |
| 2308 |
<td><span class="checkmark">✓</span></td> |
| 2309 |
<td><span class="checkmark">✓</span></td> |
| 2310 |
</tr> |
| 2311 |
<tr> |
| 2312 |
<td><?php _e( 'AI Vector Database - Cloud Storage', 'wpforo' ); ?></td> |
| 2313 |
<td><span class="crossmark">✗</span></td> |
| 2314 |
<td><span class="crossmark">✗</span></td> |
| 2315 |
<td><span class="checkmark">✓</span></td> |
| 2316 |
<td><span class="checkmark">✓</span></td> |
| 2317 |
</tr> |
| 2318 |
<tr> |
| 2319 |
<td><strong><?php _e( 'Extended Knowledge Base', 'wpforo' ); ?></strong></td> |
| 2320 |
<td><span class="crossmark">✗</span></td> |
| 2321 |
<td><span class="crossmark">✗</span></td> |
| 2322 |
<td><span class="checkmark">✓</span></td> |
| 2323 |
<td><span class="checkmark">✓</span></td> |
| 2324 |
</tr> |
| 2325 |
<tr class="feature-item"> |
| 2326 |
<td><?php _e( 'WordPress Content indexing', 'wpforo' ); ?></td> |
| 2327 |
<td><span class="crossmark">✗</span></td> |
| 2328 |
<td><span class="crossmark">✗</span></td> |
| 2329 |
<td><span class="checkmark">✓</span></td> |
| 2330 |
<td><span class="checkmark">✓</span></td> |
| 2331 |
</tr> |
| 2332 |
<tr class="feature-item"> |
| 2333 |
<td><?php _e( 'Custom Post Types indexing', 'wpforo' ); ?> </td> |
| 2334 |
<td><span class="crossmark">✗</span></td> |
| 2335 |
<td><span class="crossmark">✗</span></td> |
| 2336 |
<td><span class="checkmark">✓</span></td> |
| 2337 |
<td><span class="checkmark">✓</span></td> |
| 2338 |
</tr> |
| 2339 |
<tr class="feature-item"> |
| 2340 |
<td><?php _e( 'WooCommerce indexing', 'wpforo' ); echo '<span class="coming-soon-badge">' . esc_html__( 'Coming Soon', 'wpforo' ) . '</span>'; ?></td> |
| 2341 |
<td><span class="crossmark">✗</span></td> |
| 2342 |
<td><span class="crossmark">✗</span></td> |
| 2343 |
<td><span class="checkmark">✓</span></td> |
| 2344 |
<td><span class="checkmark">✓</span></td> |
| 2345 |
</tr> |
| 2346 |
<tr> |
| 2347 |
<td><strong><?php _e( 'Custom Knowledge Indexing', 'wpforo' ); ?></strong></td> |
| 2348 |
<td><span class="crossmark">✗</span></td> |
| 2349 |
<td><span class="crossmark">✗</span></td> |
| 2350 |
<td><span class="checkmark">✓</span></td> |
| 2351 |
<td><span class="checkmark">✓</span></td> |
| 2352 |
</tr> |
| 2353 |
<tr class="feature-item"> |
| 2354 |
<td><?php _e( 'File Indexing (TXT, MD, JSON, PDF)', 'wpforo' ); ?></td> |
| 2355 |
<td><span class="crossmark">✗</span></td> |
| 2356 |
<td><span class="crossmark">✗</span></td> |
| 2357 |
<td><span class="checkmark">✓</span></td> |
| 2358 |
<td><span class="checkmark">✓</span></td> |
| 2359 |
</tr> |
| 2360 |
|
| 2361 |
<!-- Enterprise Features --> |
| 2362 |
<tr class="feature-category"> |
| 2363 |
<td colspan="5"><span class="dashicons dashicons-admin-tools"></span> <?php _e( 'Enterprise Features', 'wpforo' ); ?></td> |
| 2364 |
</tr> |
| 2365 |
<tr> |
| 2366 |
<td><strong><?php _e( 'Developer Features', 'wpforo' ); ?></strong></td> |
| 2367 |
<td><span class="crossmark">✗</span></td> |
| 2368 |
<td><span class="crossmark">✗</span></td> |
| 2369 |
<td><span class="crossmark">✗</span></td> |
| 2370 |
<td><span class="checkmark">✓</span></td> |
| 2371 |
</tr> |
| 2372 |
<tr class="feature-item"> |
| 2373 |
<td><?php _e( 'REST API Access', 'wpforo' ); ?></td> |
| 2374 |
<td><span class="crossmark">✗</span></td> |
| 2375 |
<td><span class="crossmark">✗</span></td> |
| 2376 |
<td><span class="crossmark">✗</span></td> |
| 2377 |
<td><span class="checkmark">✓</span></td> |
| 2378 |
</tr> |
| 2379 |
<tr class="feature-item"> |
| 2380 |
<td><?php _e( 'Custom AI Models', 'wpforo' ); ?></td> |
| 2381 |
<td><span class="crossmark">✗</span></td> |
| 2382 |
<td><span class="crossmark">✗</span></td> |
| 2383 |
<td><span class="crossmark">✗</span></td> |
| 2384 |
<td><span class="checkmark">✓</span></td> |
| 2385 |
</tr> |
| 2386 |
<tr class="feature-item"> |
| 2387 |
<td><?php _e( 'Custom feature development', 'wpforo' ); ?></td> |
| 2388 |
<td><span class="crossmark">✗</span></td> |
| 2389 |
<td><span class="crossmark">✗</span></td> |
| 2390 |
<td><span class="crossmark">✗</span></td> |
| 2391 |
<td><span class="checkmark">✓</span></td> |
| 2392 |
</tr> |
| 2393 |
<tr> |
| 2394 |
<td><strong><?php _e( 'Premium Support', 'wpforo' ); ?></strong></td> |
| 2395 |
<td><span class="crossmark">✗</span></td> |
| 2396 |
<td><span class="crossmark">✗</span></td> |
| 2397 |
<td><span class="crossmark">✗</span></td> |
| 2398 |
<td><span class="checkmark">✓</span></td> |
| 2399 |
</tr> |
| 2400 |
<tr class="feature-item"> |
| 2401 |
<td><?php _e( 'Dedicated account manager', 'wpforo' ); ?></td> |
| 2402 |
<td><span class="crossmark">✗</span></td> |
| 2403 |
<td><span class="crossmark">✗</span></td> |
| 2404 |
<td><span class="crossmark">✗</span></td> |
| 2405 |
<td><span class="checkmark">✓</span></td> |
| 2406 |
</tr> |
| 2407 |
<tr class="feature-item"> |
| 2408 |
<td><?php _e( 'Enterprise Capabilities', 'wpforo' ); ?></td> |
| 2409 |
<td><span class="crossmark">✗</span></td> |
| 2410 |
<td><span class="crossmark">✗</span></td> |
| 2411 |
<td><span class="crossmark">✗</span></td> |
| 2412 |
<td><span class="checkmark">✓</span></td> |
| 2413 |
</tr> |
| 2414 |
|
| 2415 |
<!-- Bottom CTA Row --> |
| 2416 |
<tr class="cta-row"> |
| 2417 |
<td></td> |
| 2418 |
<td> |
| 2419 |
<?php if ( $current_plan === 'starter' ) : ?> |
| 2420 |
<div class="plan-active-info"> |
| 2421 |
<span class="dashicons dashicons-yes-alt"></span> |
| 2422 |
<?php _e( 'Active', 'wpforo' ); ?> |
| 2423 |
</div> |
| 2424 |
<?php elseif ( $plan_levels['starter'] < $current_level ) : ?> |
| 2425 |
<button type="button" class="button button-secondary button-cta" disabled> |
| 2426 |
<?php _e( 'Upgrade', 'wpforo' ); ?> |
| 2427 |
</button> |
| 2428 |
<?php else : ?> |
| 2429 |
<button type="button" class="button button-secondary button-cta wpforo-ai-upgrade-btn" data-plan="starter" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2430 |
<?php _e( 'Upgrade', 'wpforo' ); ?> |
| 2431 |
</button> |
| 2432 |
<?php endif; ?> |
| 2433 |
</td> |
| 2434 |
<td> |
| 2435 |
<?php if ( $current_plan === 'professional' ) : ?> |
| 2436 |
<div class="plan-active-info"> |
| 2437 |
<span class="dashicons dashicons-yes-alt"></span> |
| 2438 |
<?php _e( 'Active', 'wpforo' ); ?> |
| 2439 |
</div> |
| 2440 |
<?php elseif ( $plan_levels['professional'] < $current_level ) : ?> |
| 2441 |
<button type="button" class="button button-secondary button-cta" disabled> |
| 2442 |
<?php _e( 'Upgrade', 'wpforo' ); ?> |
| 2443 |
</button> |
| 2444 |
<?php else : ?> |
| 2445 |
<button type="button" class="button button-secondary button-cta wpforo-ai-upgrade-btn" data-plan="professional" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2446 |
<?php _e( 'Upgrade', 'wpforo' ); ?> |
| 2447 |
</button> |
| 2448 |
<?php endif; ?> |
| 2449 |
</td> |
| 2450 |
<td> |
| 2451 |
<?php if ( $current_plan === 'business' ) : ?> |
| 2452 |
<div class="plan-active-info"> |
| 2453 |
<span class="dashicons dashicons-yes-alt"></span> |
| 2454 |
<?php _e( 'Active', 'wpforo' ); ?> |
| 2455 |
</div> |
| 2456 |
<?php elseif ( $plan_levels['business'] < $current_level ) : ?> |
| 2457 |
<button type="button" class="button button-secondary button-cta" disabled> |
| 2458 |
<?php _e( 'Upgrade', 'wpforo' ); ?> |
| 2459 |
</button> |
| 2460 |
<?php else : ?> |
| 2461 |
<button type="button" class="button button-secondary button-cta wpforo-ai-upgrade-btn" data-plan="business" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2462 |
<?php _e( 'Upgrade', 'wpforo' ); ?> |
| 2463 |
</button> |
| 2464 |
<?php endif; ?> |
| 2465 |
</td> |
| 2466 |
<td> |
| 2467 |
<?php if ( $current_plan === 'enterprise' ) : ?> |
| 2468 |
<div class="plan-active-info"> |
| 2469 |
<span class="dashicons dashicons-yes-alt"></span> |
| 2470 |
<?php _e( 'Active', 'wpforo' ); ?> |
| 2471 |
</div> |
| 2472 |
<?php else : ?> |
| 2473 |
<a href="https://wpforo.com/gvectors-ai/#gvai-contact" target="_blank" class="button button-secondary" style="padding: 5px 20px;"> |
| 2474 |
<?php _e( 'Contact Us', 'wpforo' ) ?> |
| 2475 |
</a> |
| 2476 |
<?php endif; ?> |
| 2477 |
</td> |
| 2478 |
</tr> |
| 2479 |
</tbody> |
| 2480 |
</table> |
| 2481 |
</div> |
| 2482 |
|
| 2483 |
<?php |
| 2484 |
$enabled_providers = wpforo_ai_get_enabled_providers(); |
| 2485 |
$default_provider = wpforo_ai_get_default_provider(); |
| 2486 |
$show_toggle = count( $enabled_providers ) > 1; |
| 2487 |
?> |
| 2488 |
|
| 2489 |
<?php if ( $show_toggle ) : ?> |
| 2490 |
<!-- Payment Provider Toggle --> |
| 2491 |
<div class="wpforo-ai-provider-toggle" style="margin-top: 15px; padding: 12px 20px; background: #f8f9fa; border: 1px solid #ddd; border-radius: 6px; display: flex; align-items: center; gap: 20px;"> |
| 2492 |
<span style="font-weight: 500; color: #333;"> |
| 2493 |
<span class="dashicons dashicons-money-alt" style="vertical-align: middle; margin-right: 4px;"></span> |
| 2494 |
<?php _e( 'Payment Method:', 'wpforo' ); ?> |
| 2495 |
</span> |
| 2496 |
<?php if ( in_array( 'paddle', $enabled_providers, true ) ) : ?> |
| 2497 |
<label style="display: flex; align-items: center; gap: 5px; cursor: pointer;"> |
| 2498 |
<input type="radio" name="wpforo_ai_payment_provider" value="paddle" <?php checked( $default_provider, 'paddle' ); ?>> |
| 2499 |
<?php _e( 'Paddle (Credit Card, PayPal)', 'wpforo' ); ?> |
| 2500 |
</label> |
| 2501 |
<?php endif; ?> |
| 2502 |
<?php if ( in_array( 'freemius', $enabled_providers, true ) ) : ?> |
| 2503 |
<label style="display: flex; align-items: center; gap: 5px; cursor: pointer;"> |
| 2504 |
<input type="radio" name="wpforo_ai_payment_provider" value="freemius" <?php checked( $default_provider, 'freemius' ); ?>> |
| 2505 |
<?php _e( 'Freemius', 'wpforo' ); ?> |
| 2506 |
</label> |
| 2507 |
<?php endif; ?> |
| 2508 |
</div> |
| 2509 |
<?php endif; ?> |
| 2510 |
|
| 2511 |
<div class="wpforo-ai-powered-by"> |
| 2512 |
<span class="dashicons dashicons-lock"></span> |
| 2513 |
<?php |
| 2514 |
if ( ! $show_toggle && in_array( 'paddle', $enabled_providers, true ) ) { |
| 2515 |
_e( 'Payment and Subscription Management is Powered by Paddle - Secure Checkout', 'wpforo' ); |
| 2516 |
} elseif ( ! $show_toggle && in_array( 'freemius', $enabled_providers, true ) ) { |
| 2517 |
_e( 'Payment and Subscription Management is Powered by Freemius - Secure Checkout', 'wpforo' ); |
| 2518 |
} else { |
| 2519 |
_e( 'Secure Payment Processing', 'wpforo' ); |
| 2520 |
} |
| 2521 |
?> |
| 2522 |
</div> |
| 2523 |
|
| 2524 |
<!-- Checkout Configurations --> |
| 2525 |
<script type="text/javascript"> |
| 2526 |
<?php if ( in_array( 'freemius', $enabled_providers, true ) ) : ?> |
| 2527 |
// Freemius checkout configurations for each plan |
| 2528 |
window.wpforoFreemiusCheckout = { |
| 2529 |
tenant_id: <?php echo json_encode( $tenant_id ); ?>, |
| 2530 |
plans: { |
| 2531 |
starter: <?php echo json_encode( wpforo_ai_get_upgrade_url( $tenant_id, 'starter' ) ); ?>, |
| 2532 |
professional: <?php echo json_encode( wpforo_ai_get_upgrade_url( $tenant_id, 'professional' ) ); ?>, |
| 2533 |
business: <?php echo json_encode( wpforo_ai_get_upgrade_url( $tenant_id, 'business' ) ); ?>, |
| 2534 |
enterprise: <?php echo json_encode( wpforo_ai_get_upgrade_url( $tenant_id, 'enterprise' ) ); ?> |
| 2535 |
} |
| 2536 |
}; |
| 2537 |
<?php endif; ?> |
| 2538 |
|
| 2539 |
<?php if ( in_array( 'paddle', $enabled_providers, true ) ) : ?> |
| 2540 |
// Paddle checkout configurations |
| 2541 |
<?php $paddle_pricing = wpforo_ai_get_paddle_pricing(); ?> |
| 2542 |
window.wpforoPaddleCheckout = { |
| 2543 |
tenant_id: <?php echo json_encode( $tenant_id ); ?>, |
| 2544 |
plans: { |
| 2545 |
starter: { price_id: <?php echo json_encode( $paddle_pricing['plans']['starter']['price_id'] ); ?> }, |
| 2546 |
professional: { price_id: <?php echo json_encode( $paddle_pricing['plans']['professional']['price_id'] ); ?> }, |
| 2547 |
business: { price_id: <?php echo json_encode( $paddle_pricing['plans']['business']['price_id'] ); ?> }, |
| 2548 |
enterprise: { price_id: <?php echo json_encode( $paddle_pricing['plans']['enterprise']['price_id'] ); ?> } |
| 2549 |
}, |
| 2550 |
creditPacks: { |
| 2551 |
'500': { price_id: <?php echo json_encode( $paddle_pricing['credit_packs']['500']['price_id'] ); ?> }, |
| 2552 |
'1500': { price_id: <?php echo json_encode( $paddle_pricing['credit_packs']['1500']['price_id'] ); ?> }, |
| 2553 |
'4500': { price_id: <?php echo json_encode( $paddle_pricing['credit_packs']['4500']['price_id'] ); ?> }, |
| 2554 |
'15000': { price_id: <?php echo json_encode( $paddle_pricing['credit_packs']['15000']['price_id'] ); ?> } |
| 2555 |
} |
| 2556 |
}; |
| 2557 |
<?php endif; ?> |
| 2558 |
|
| 2559 |
// Active payment provider and enabled providers |
| 2560 |
window.wpforoPaymentProvider = <?php echo json_encode( $default_provider ); ?>; |
| 2561 |
window.wpforoEnabledProviders = <?php echo json_encode( $enabled_providers ); ?>; |
| 2562 |
</script> |
| 2563 |
<?php |
| 2564 |
} |
| 2565 |
|
| 2566 |
/** |
| 2567 |
* Render credit packs section |
| 2568 |
* |
| 2569 |
* @param string $tenant_id Tenant ID for purchase URLs |
| 2570 |
*/ |
| 2571 |
function wpforo_ai_render_credit_packs( $tenant_id ) { |
| 2572 |
// Fetch dynamic pricing from Freemius API (with fallback to defaults) |
| 2573 |
$pricing = wpforo_ai_get_freemius_pricing(); |
| 2574 |
$credit_packs = $pricing['credit_packs']; |
| 2575 |
?> |
| 2576 |
<div class="wpforo-ai-credit-packs-wrapper"> |
| 2577 |
<div class="credit-packs-header"> |
| 2578 |
<p class="credit-packs-description"> |
| 2579 |
<?php printf( __( 'Need more credits? Purchase one-time credit packs. Credits accumulate with your subscription credits up to your plan\'s maximum (one year of subscription plan credits) and can be used %s.', 'wpforo' ), '<span style="color: #990000">' . __('as long as you have an active subscription', 'wpforo' ) . '</span>' ); ?> |
| 2580 |
</p> |
| 2581 |
</div> |
| 2582 |
|
| 2583 |
<div class="wpforo-ai-credit-packs-table"> |
| 2584 |
<!-- 500 Credits Pack --> |
| 2585 |
<div class="credit-pack"> |
| 2586 |
<div class="credit-pack-header"> |
| 2587 |
<h4><?php _e( '500 Credits', 'wpforo' ); ?></h4> |
| 2588 |
<div class="credit-pack-price">$<?php echo esc_html( number_format( $credit_packs['500']['price'], 0 ) ); ?><span class="credit-pack-period"><?php _e( 'one-time', 'wpforo' ); ?></span></div> |
| 2589 |
</div> |
| 2590 |
<div class="credit-pack-action"> |
| 2591 |
<button type="button" class="button button-large wpforo-ai-buy-credits-btn" data-pack="500" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2592 |
<?php _e( 'Buy Now', 'wpforo' ); ?> |
| 2593 |
</button> |
| 2594 |
</div> |
| 2595 |
</div> |
| 2596 |
|
| 2597 |
<!-- 1500 Credits Pack --> |
| 2598 |
<div class="credit-pack"> |
| 2599 |
<div class="credit-pack-header"> |
| 2600 |
<h4><?php _e( '1,500 Credits', 'wpforo' ); ?></h4> |
| 2601 |
<div class="credit-pack-price">$<?php echo esc_html( number_format( $credit_packs['1500']['price'], 0 ) ); ?><span class="credit-pack-period"><?php _e( 'one-time', 'wpforo' ); ?></span></div> |
| 2602 |
</div> |
| 2603 |
<div class="credit-pack-action"> |
| 2604 |
<button type="button" class="button button-large wpforo-ai-buy-credits-btn" data-pack="1500" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2605 |
<?php _e( 'Buy Now', 'wpforo' ); ?> |
| 2606 |
</button> |
| 2607 |
</div> |
| 2608 |
</div> |
| 2609 |
|
| 2610 |
<!-- 4500 Credits Pack --> |
| 2611 |
<div class="credit-pack"> |
| 2612 |
<div class="credit-pack-header"> |
| 2613 |
<h4><?php _e( '4,500 Credits', 'wpforo' ); ?></h4> |
| 2614 |
<div class="credit-pack-price">$<?php echo esc_html( number_format( $credit_packs['4500']['price'], 0 ) ); ?><span class="credit-pack-period"><?php _e( 'one-time', 'wpforo' ); ?></span></div> |
| 2615 |
</div> |
| 2616 |
<div class="credit-pack-action"> |
| 2617 |
<button type="button" class="button button-large wpforo-ai-buy-credits-btn" data-pack="4500" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2618 |
<?php _e( 'Buy Now', 'wpforo' ); ?> |
| 2619 |
</button> |
| 2620 |
</div> |
| 2621 |
</div> |
| 2622 |
|
| 2623 |
<!-- 15000 Credits Pack --> |
| 2624 |
<div class="credit-pack"> |
| 2625 |
<div class="credit-pack-header"> |
| 2626 |
<h4><?php _e( '15,000 Credits', 'wpforo' ); ?></h4> |
| 2627 |
<div class="credit-pack-price">$<?php echo esc_html( number_format( $credit_packs['15000']['price'], 0 ) ); ?><span class="credit-pack-period"><?php _e( 'one-time', 'wpforo' ); ?></span></div> |
| 2628 |
</div> |
| 2629 |
<div class="credit-pack-action"> |
| 2630 |
<button type="button" class="button button-large wpforo-ai-buy-credits-btn" data-pack="15000" data-tenant-id="<?php echo esc_attr( $tenant_id ); ?>"> |
| 2631 |
<?php _e( 'Buy Now', 'wpforo' ); ?> |
| 2632 |
</button> |
| 2633 |
</div> |
| 2634 |
</div> |
| 2635 |
</div> |
| 2636 |
|
| 2637 |
<div class="wpforo-ai-credit-packs-note"> |
| 2638 |
<p><strong><?php _e( 'Important:', 'wpforo' ); ?></strong> <?php _e( 'Credit packs are one-time purchases that accumulate with your monthly subscription credits up to your plan\'s maximum accumulation limit (one year of subscription plan credits). Credits can only be used while you have an active subscription. If your subscription expires, your credits will remain in your account but cannot be used until you reactivate your subscription.', 'wpforo' ); ?></p> |
| 2639 |
</div> |
| 2640 |
</div> |
| 2641 |
|
| 2642 |
<!-- Credit Pack Checkout Configurations --> |
| 2643 |
<script type="text/javascript"> |
| 2644 |
<?php $credit_providers = wpforo_ai_get_enabled_providers(); ?> |
| 2645 |
<?php if ( in_array( 'freemius', $credit_providers, true ) ) : ?> |
| 2646 |
// Add credit pack configurations to existing wpforoFreemiusCheckout object |
| 2647 |
if (typeof window.wpforoFreemiusCheckout === 'undefined') { |
| 2648 |
window.wpforoFreemiusCheckout = { tenant_id: <?php echo json_encode( $tenant_id ); ?> }; |
| 2649 |
} |
| 2650 |
window.wpforoFreemiusCheckout.creditPacks = { |
| 2651 |
'500': <?php echo json_encode( wpforo_ai_get_credit_pack_config( $tenant_id, '500' ) ); ?>, |
| 2652 |
'1500': <?php echo json_encode( wpforo_ai_get_credit_pack_config( $tenant_id, '1500' ) ); ?>, |
| 2653 |
'4500': <?php echo json_encode( wpforo_ai_get_credit_pack_config( $tenant_id, '4500' ) ); ?>, |
| 2654 |
'15000': <?php echo json_encode( wpforo_ai_get_credit_pack_config( $tenant_id, '15000' ) ); ?> |
| 2655 |
}; |
| 2656 |
<?php endif; ?> |
| 2657 |
</script> |
| 2658 |
<?php |
| 2659 |
} |
| 2660 |
|
| 2661 |
/** |
| 2662 |
* Get user data for Freemius checkout |
| 2663 |
* |
| 2664 |
* Returns the current WordPress user's email and name for pre-filling the checkout form. |
| 2665 |
* Only uses actual first_name and last_name from user meta - no fallbacks to avoid wrong data. |
| 2666 |
* |
| 2667 |
* @return array User data with 'email', 'first', and 'last' keys |
| 2668 |
*/ |
| 2669 |
function wpforo_ai_get_freemius_user_data() { |
| 2670 |
$current_user = wp_get_current_user(); |
| 2671 |
|
| 2672 |
// Get email - prefer current user's email, fallback to admin email |
| 2673 |
$email = ! empty( $current_user->user_email ) ? $current_user->user_email : get_option( 'admin_email' ); |
| 2674 |
|
| 2675 |
// Get first name and last name from user meta only - no fallbacks |
| 2676 |
// Empty is better than wrong data (like website title) |
| 2677 |
$first_name = ! empty( $current_user->first_name ) ? $current_user->first_name : ''; |
| 2678 |
$last_name = ! empty( $current_user->last_name ) ? $current_user->last_name : ''; |
| 2679 |
|
| 2680 |
return [ |
| 2681 |
'email' => $email, |
| 2682 |
'first' => $first_name, |
| 2683 |
'last' => $last_name, |
| 2684 |
]; |
| 2685 |
} |
| 2686 |
|
| 2687 |
/** |
| 2688 |
* Get Freemius upgrade URL |
| 2689 |
* |
| 2690 |
* @param string $tenant_id Tenant ID |
| 2691 |
* @param string $plan Plan name ('starter', 'professional', 'business', 'enterprise') |
| 2692 |
* @return string Checkout URL |
| 2693 |
*/ |
| 2694 |
function wpforo_ai_get_upgrade_url( $tenant_id, $plan = 'professional' ) { |
| 2695 |
// Freemius plugin configuration |
| 2696 |
// wpForo AI Addon ID: 21923 |
| 2697 |
$freemius_plugin_id = wpforo_get_option( 'ai_freemius_plugin_id', '21923' ); |
| 2698 |
|
| 2699 |
// Ensure plugin_id is never empty |
| 2700 |
if ( empty( $freemius_plugin_id ) ) { |
| 2701 |
$freemius_plugin_id = '21923'; |
| 2702 |
} |
| 2703 |
|
| 2704 |
// Fetch dynamic pricing from Freemius API (with fallback to defaults) |
| 2705 |
$pricing = wpforo_ai_get_freemius_pricing(); |
| 2706 |
$plans = $pricing['plans']; |
| 2707 |
|
| 2708 |
$config = [ |
| 2709 |
'starter' => [ |
| 2710 |
'plugin_id' => $freemius_plugin_id, |
| 2711 |
'plan_id' => $plans['starter']['plan_id'], |
| 2712 |
'pricing_id' => $plans['starter']['pricing_id'], |
| 2713 |
], |
| 2714 |
'professional' => [ |
| 2715 |
'plugin_id' => $freemius_plugin_id, |
| 2716 |
'plan_id' => $plans['professional']['plan_id'], |
| 2717 |
'pricing_id' => $plans['professional']['pricing_id'], |
| 2718 |
], |
| 2719 |
'business' => [ |
| 2720 |
'plugin_id' => $freemius_plugin_id, |
| 2721 |
'plan_id' => $plans['business']['plan_id'], |
| 2722 |
'pricing_id' => $plans['business']['pricing_id'], |
| 2723 |
], |
| 2724 |
'enterprise' => [ |
| 2725 |
'plugin_id' => $freemius_plugin_id, |
| 2726 |
'plan_id' => $plans['enterprise']['plan_id'], |
| 2727 |
'pricing_id' => $plans['enterprise']['pricing_id'], |
| 2728 |
], |
| 2729 |
]; |
| 2730 |
|
| 2731 |
$plan_config = isset( $config[ $plan ] ) ? $config[ $plan ] : $config['professional']; |
| 2732 |
|
| 2733 |
// Ensure plan_config is valid |
| 2734 |
if ( ! is_array( $plan_config ) ) { |
| 2735 |
$plan_config = $config['professional']; |
| 2736 |
} |
| 2737 |
|
| 2738 |
// Get API Gateway webhook URL |
| 2739 |
$webhook_url = WPF()->ai_client->get_api_base_url() . '/v1/freemius/webhook'; |
| 2740 |
|
| 2741 |
// Build config object for JavaScript (not a URL) |
| 2742 |
$plugin_id = isset( $plan_config['plugin_id'] ) && ! empty( $plan_config['plugin_id'] ) ? $plan_config['plugin_id'] : '21923'; |
| 2743 |
$plan_id = isset( $plan_config['plan_id'] ) && ! empty( $plan_config['plan_id'] ) ? $plan_config['plan_id'] : $plans['professional']['plan_id']; |
| 2744 |
$pricing_id = isset( $plan_config['pricing_id'] ) && ! empty( $plan_config['pricing_id'] ) ? $plan_config['pricing_id'] : $plans['professional']['pricing_id']; |
| 2745 |
|
| 2746 |
return [ |
| 2747 |
'plugin_id' => $plugin_id, |
| 2748 |
'plan_id' => $plan_id, |
| 2749 |
'pricing_id' => $pricing_id, |
| 2750 |
'public_key' => 'pk_bbb26ca8c136ce743c4661e2dd23f', // Freemius Public Key |
| 2751 |
'billing_cycle' => 'monthly', |
| 2752 |
'currency' => 'usd', |
| 2753 |
'success' => admin_url( 'admin.php?page=wpforo-ai&upgraded=1&plan=' . $plan ), |
| 2754 |
'cancel' => admin_url( 'admin.php?page=wpforo-ai' ), |
| 2755 |
'webhook_url' => $webhook_url, |
| 2756 |
'user' => wpforo_ai_get_freemius_user_data(), |
| 2757 |
'metadata' => [ |
| 2758 |
'tenant_id' => $tenant_id, // CRITICAL: Pass tenant_id so webhook can identify tenant |
| 2759 |
], |
| 2760 |
]; |
| 2761 |
} |
| 2762 |
|
| 2763 |
/** |
| 2764 |
* Get Freemius credit pack configuration |
| 2765 |
* |
| 2766 |
* @param string $tenant_id Tenant ID |
| 2767 |
* @param string $pack Pack size ('500', '1500', '4500', '15000') |
| 2768 |
* @return array Checkout configuration |
| 2769 |
*/ |
| 2770 |
function wpforo_ai_get_credit_pack_config( $tenant_id, $pack = '1500' ) { |
| 2771 |
// Freemius plugin configuration |
| 2772 |
// AI Credits Addon ID: 21955 (different from main wpForo AI plugin 21923) |
| 2773 |
$freemius_addon_id = wpforo_get_option( 'ai_freemius_addon_id', '21955' ); |
| 2774 |
|
| 2775 |
// Ensure addon_id is never empty |
| 2776 |
if ( empty( $freemius_addon_id ) ) { |
| 2777 |
$freemius_addon_id = '21955'; |
| 2778 |
} |
| 2779 |
|
| 2780 |
// Fetch dynamic pricing from Freemius API (with fallback to defaults) |
| 2781 |
$pricing = wpforo_ai_get_freemius_pricing(); |
| 2782 |
$credit_packs = $pricing['credit_packs']; |
| 2783 |
|
| 2784 |
// Credit pack add-on plan IDs from Freemius |
| 2785 |
$config = [ |
| 2786 |
'500' => [ |
| 2787 |
'plugin_id' => $freemius_addon_id, |
| 2788 |
'plan_id' => $credit_packs['500']['plan_id'], |
| 2789 |
'pricing_id' => $credit_packs['500']['pricing_id'], |
| 2790 |
], |
| 2791 |
'1500' => [ |
| 2792 |
'plugin_id' => $freemius_addon_id, |
| 2793 |
'plan_id' => $credit_packs['1500']['plan_id'], |
| 2794 |
'pricing_id' => $credit_packs['1500']['pricing_id'], |
| 2795 |
], |
| 2796 |
'4500' => [ |
| 2797 |
'plugin_id' => $freemius_addon_id, |
| 2798 |
'plan_id' => $credit_packs['4500']['plan_id'], |
| 2799 |
'pricing_id' => $credit_packs['4500']['pricing_id'], |
| 2800 |
], |
| 2801 |
'15000' => [ |
| 2802 |
'plugin_id' => $freemius_addon_id, |
| 2803 |
'plan_id' => $credit_packs['15000']['plan_id'], |
| 2804 |
'pricing_id' => $credit_packs['15000']['pricing_id'], |
| 2805 |
], |
| 2806 |
]; |
| 2807 |
|
| 2808 |
$pack_config = isset( $config[ $pack ] ) ? $config[ $pack ] : $config['1500']; |
| 2809 |
|
| 2810 |
// Ensure pack_config is valid |
| 2811 |
if ( ! is_array( $pack_config ) ) { |
| 2812 |
$pack_config = $config['1500']; |
| 2813 |
} |
| 2814 |
|
| 2815 |
// Get API Gateway webhook URL |
| 2816 |
$webhook_url = WPF()->ai_client->get_api_base_url() . '/v1/freemius/webhook'; |
| 2817 |
|
| 2818 |
// Build config object for JavaScript (not a URL) |
| 2819 |
$plugin_id = isset( $pack_config['plugin_id'] ) && ! empty( $pack_config['plugin_id'] ) ? $pack_config['plugin_id'] : '21955'; |
| 2820 |
$plan_id = isset( $pack_config['plan_id'] ) && ! empty( $pack_config['plan_id'] ) ? $pack_config['plan_id'] : $credit_packs['1500']['plan_id']; |
| 2821 |
$pricing_id = isset( $pack_config['pricing_id'] ) && ! empty( $pack_config['pricing_id'] ) ? $pack_config['pricing_id'] : $credit_packs['1500']['pricing_id']; |
| 2822 |
|
| 2823 |
return [ |
| 2824 |
'plugin_id' => $plugin_id, |
| 2825 |
'plan_id' => $plan_id, |
| 2826 |
'pricing_id' => $pricing_id, |
| 2827 |
'public_key' => 'pk_d241fb18a0097c75e4de7c12d8b67', // AI Credits Addon Public Key |
| 2828 |
'billing_cycle' => 'one-time', |
| 2829 |
'currency' => 'usd', |
| 2830 |
'success' => admin_url( 'admin.php?page=wpforo-ai&credits_purchased=1&pack=' . $pack ), |
| 2831 |
'cancel' => admin_url( 'admin.php?page=wpforo-ai' ), |
| 2832 |
'webhook_url' => $webhook_url, |
| 2833 |
'user' => wpforo_ai_get_freemius_user_data(), |
| 2834 |
'metadata' => [ |
| 2835 |
'tenant_id' => $tenant_id, // CRITICAL: Pass tenant_id so webhook can identify tenant |
| 2836 |
'is_addon' => true, // Flag to distinguish add-on from subscription |
| 2837 |
], |
| 2838 |
]; |
| 2839 |
} |
| 2840 |
|
| 2841 |
/** |
| 2842 |
* Get manage subscription URL based on payment provider |
| 2843 |
* |
| 2844 |
* For Paddle: customer-portal.paddle.com/cpl_{ID} (seller-specific portal with email login) |
| 2845 |
* For Freemius: customers.gvectors.com (Freemius customer portal) |
| 2846 |
* |
| 2847 |
* @return string Manage subscription URL |
| 2848 |
*/ |
| 2849 |
function wpforo_ai_get_manage_subscription_url( $provider = '' ) { |
| 2850 |
// If no provider specified, use the stored default |
| 2851 |
if ( ! $provider ) { |
| 2852 |
$provider = get_option( 'wpforo_ai_payment_provider', '' ); |
| 2853 |
} |
| 2854 |
|
| 2855 |
if ( $provider === 'paddle' ) { |
| 2856 |
// Paddle customer portal with seller-specific CPL ID |
| 2857 |
// Shows email login page where customers get a magic link |
| 2858 |
$url = 'https://customer-portal.paddle.com/cpl_01f49qd36rqh2vswk36847drxt'; |
| 2859 |
} else { |
| 2860 |
$url = 'https://customers.gvectors.com'; |
| 2861 |
} |
| 2862 |
|
| 2863 |
return apply_filters( 'wpforo_ai_manage_subscription_url', $url, $provider ); |
| 2864 |
} |
| 2865 |
|
| 2866 |
/** |
| 2867 |
* Get CSS class for credit status based on percentage remaining |
| 2868 |
* |
| 2869 |
* @param int $percent Percentage remaining |
| 2870 |
* @return string CSS class |
| 2871 |
*/ |
| 2872 |
function wpforo_ai_get_credit_status_class( $percent ) { |
| 2873 |
if ( $percent >= 50 ) { |
| 2874 |
return 'status-good'; |
| 2875 |
} elseif ( $percent >= 20 ) { |
| 2876 |
return 'status-warning'; |
| 2877 |
} else { |
| 2878 |
return 'status-critical'; |
| 2879 |
} |
| 2880 |
} |
| 2881 |
|
| 2882 |
/** |
| 2883 |
* Format date for display |
| 2884 |
* |
| 2885 |
* @param string $date ISO 8601 date string |
| 2886 |
* @return string Formatted date |
| 2887 |
*/ |
| 2888 |
|