| 1 |
<?php |
| 2 |
/** |
| 3 |
* AI Features - WordPress Content Indexing Tab |
| 4 |
* |
| 5 |
* Completely isolated tab for WordPress post/page/CPT indexing. |
| 6 |
* Separate from forum content indexing in AI Content Indexing tab. |
| 7 |
* |
| 8 |
* @package wpForo |
| 9 |
* @subpackage Admin |
| 10 |
* @since 3.0.0 |
| 11 |
*/ |
| 12 |
|
| 13 |
if ( ! defined( 'ABSPATH' ) ) { |
| 14 |
exit; |
| 15 |
} |
| 16 |
|
| 17 |
/** |
| 18 |
* Render WordPress Content Indexing tab content |
| 19 |
* |
| 20 |
* @param bool $is_connected Whether tenant is connected to AI service |
| 21 |
* @param array $status Tenant status data from API |
| 22 |
*/ |
| 23 |
function wpforo_ai_render_wp_indexing_tab( $is_connected, $status ) { |
| 24 |
if ( ! $is_connected ) { |
| 25 |
?> |
| 26 |
<div class="wpforo-ai-box wpforo-ai-not-connected-notice"> |
| 27 |
<div class="wpforo-ai-box-body"> |
| 28 |
<div class="wpforo-ai-status-badge status-warning"> |
| 29 |
<span class="dashicons dashicons-warning"></span> |
| 30 |
<?php _e( 'Not Connected', 'wpforo' ); ?> |
| 31 |
</div> |
| 32 |
<p><?php _e( 'Please connect to wpForo AI API first in the Overview tab to enable WordPress Content Indexing.', 'wpforo' ); ?></p> |
| 33 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforo-ai&tab=overview' ) ); ?>" class="button button-primary"> |
| 34 |
<?php _e( 'Go to Overview', 'wpforo' ); ?> |
| 35 |
</a> |
| 36 |
</div> |
| 37 |
</div> |
| 38 |
<?php |
| 39 |
return; |
| 40 |
} |
| 41 |
|
| 42 |
// Feature gate check - Business+ plan required |
| 43 |
$wpf_ai_wp_indexing_available = isset( WPF()->ai_client ) && WPF()->ai_client->is_feature_available( 'wordpress_content_indexing' ); |
| 44 |
if ( ! $wpf_ai_wp_indexing_available ) { |
| 45 |
?> |
| 46 |
<div class="wpforo-ai-box wpforo-ai-upgrade-notice"> |
| 47 |
<div class="wpforo-ai-box-body"> |
| 48 |
<div class="wpforo-ai-status-badge status-warning"> |
| 49 |
<span class="dashicons dashicons-lock"></span> |
| 50 |
<?php _e( 'Business Plan Required', 'wpforo' ); ?> |
| 51 |
</div> |
| 52 |
<p><?php _e( 'WordPress Content Indexing is available on Business and Enterprise plans. Upgrade to index WordPress posts, pages, and custom post types for AI-powered search.', 'wpforo' ); ?></p> |
| 53 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforo-ai&tab=overview' ) ); ?>" class="button button-primary"> |
| 54 |
<?php _e( 'View Plans', 'wpforo' ); ?> |
| 55 |
</a> |
| 56 |
</div> |
| 57 |
</div> |
| 58 |
<?php |
| 59 |
return; |
| 60 |
} |
| 61 |
|
| 62 |
// Get storage mode from main board (WordPress content is global, not board-specific) |
| 63 |
$storage_manager = WPF()->vector_storage->for_board( 0 ); |
| 64 |
$storage_mode = $storage_manager->get_storage_mode(); |
| 65 |
|
| 66 |
// Get WordPress auto-indexing option (global, not board-specific) |
| 67 |
$wp_auto_indexing_enabled = (bool) get_option( 'wpforo_ai_wp_auto_indexing_enabled', 0 ); |
| 68 |
|
| 69 |
// Get WordPress image indexing option |
| 70 |
$wp_image_indexing_enabled = (bool) get_option( 'wpforo_ai_wp_image_indexing_enabled', 0 ); |
| 71 |
|
| 72 |
// Get post types from the indexer |
| 73 |
$wp_post_types = []; |
| 74 |
if ( isset( WPF()->ai_wp_indexer ) ) { |
| 75 |
$wp_post_types = WPF()->ai_wp_indexer->get_public_post_types(); |
| 76 |
} |
| 77 |
|
| 78 |
// Calculate totals |
| 79 |
$wp_total_content = 0; |
| 80 |
foreach ( $wp_post_types as $type ) { |
| 81 |
$wp_total_content += $type['count']; |
| 82 |
} |
| 83 |
|
| 84 |
// Get initial indexed counts for page load |
| 85 |
$wp_initial_status = null; |
| 86 |
$wp_initial_indexed = 0; |
| 87 |
$wp_is_indexing = false; |
| 88 |
$wp_last_activity = null; |
| 89 |
if ( isset( WPF()->ai_wp_indexer ) ) { |
| 90 |
$wp_initial_status = WPF()->ai_wp_indexer->get_indexing_status( true ); |
| 91 |
if ( ! is_wp_error( $wp_initial_status ) ) { |
| 92 |
$wp_initial_indexed = (int) ( $wp_initial_status['total_indexed'] ?? 0 ); |
| 93 |
$wp_is_indexing = (bool) ( $wp_initial_status['is_indexing'] ?? false ); |
| 94 |
$wp_last_activity = $wp_initial_status['last_indexed_at'] ?? null; |
| 95 |
} |
| 96 |
} |
| 97 |
|
| 98 |
// Get remaining credits from subscription data |
| 99 |
$remaining_credits = 0; |
| 100 |
if ( isset( $status['subscription']['credits_remaining'] ) ) { |
| 101 |
$remaining_credits = (int) $status['subscription']['credits_remaining']; |
| 102 |
} |
| 103 |
?> |
| 104 |
<div class="wpforo-ai-wp-indexing-tab"> |
| 105 |
|
| 106 |
<!-- Indexing Status Box --> |
| 107 |
<div id="wp-indexing-status-box" class="wpforo-ai-box wpforo-ai-wp-status-box"> |
| 108 |
<div class="wpforo-ai-box-header"> |
| 109 |
<h2> |
| 110 |
<span class="dashicons dashicons-chart-bar"></span> |
| 111 |
<?php _e( 'Indexing Status', 'wpforo' ); ?> |
| 112 |
</h2> |
| 113 |
<div class="wpforo-ai-header-actions"> |
| 114 |
<button type="button" class="button button-small wpforo-ai-wp-refresh-status" data-loading-text="<?php esc_attr_e( 'Refreshing...', 'wpforo' ); ?>"> |
| 115 |
<span class="dashicons dashicons-update"></span> |
| 116 |
<?php _e( 'Refresh Status', 'wpforo' ); ?> |
| 117 |
</button> |
| 118 |
</div> |
| 119 |
</div> |
| 120 |
<div class="wpforo-ai-box-body"> |
| 121 |
<div class="wpforo-ai-wp-status-grid"> |
| 122 |
<div class="wpforo-ai-wp-status-item"> |
| 123 |
<div class="status-label"><?php _e( 'Storage Mode', 'wpforo' ); ?></div> |
| 124 |
<div class="status-value"> |
| 125 |
<?php if ( $storage_mode === 'cloud' ) : ?> |
| 126 |
<span class="dashicons dashicons-cloud"></span> |
| 127 |
<?php _e( 'Cloud (AWS S3 Vectors)', 'wpforo' ); ?> |
| 128 |
<?php else : ?> |
| 129 |
<span class="dashicons dashicons-database"></span> |
| 130 |
<?php _e( 'Local (WordPress Database)', 'wpforo' ); ?> |
| 131 |
<?php endif; ?> |
| 132 |
</div> |
| 133 |
<div class="status-action"> |
| 134 |
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforo-ai&tab=rag_indexing' ) ); ?>"> |
| 135 |
<?php _e( 'Change in AI Content Indexing', 'wpforo' ); ?> → |
| 136 |
</a> |
| 137 |
</div> |
| 138 |
</div> |
| 139 |
|
| 140 |
<div class="wpforo-ai-wp-status-item wpforo-ai-wp-stat-large"> |
| 141 |
<div class="status-label"><?php _e( 'Current Status', 'wpforo' ); ?></div> |
| 142 |
<div class="status-value <?php echo $wp_is_indexing ? 'status-active' : 'status-idle'; ?>" id="wp-indexing-status"> |
| 143 |
<?php if ( $wp_is_indexing ) : ?> |
| 144 |
<span class="dashicons dashicons-update-alt wpforo-wp-indexing-spin"></span> |
| 145 |
<?php _e( 'Indexing...', 'wpforo' ); ?> |
| 146 |
<?php else : ?> |
| 147 |
<span class="dashicons dashicons-yes-alt"></span> |
| 148 |
<?php _e( 'Idle', 'wpforo' ); ?> |
| 149 |
<?php endif; ?> |
| 150 |
</div> |
| 151 |
</div> |
| 152 |
|
| 153 |
<div class="wpforo-ai-wp-status-item wpforo-ai-wp-stat-large"> |
| 154 |
<div class="status-label"><?php _e( 'Last Activity', 'wpforo' ); ?></div> |
| 155 |
<div class="status-value" id="wp-last-activity"> |
| 156 |
<?php |
| 157 |
if ( $wp_last_activity ) { |
| 158 |
echo esc_html( wpforo_ai_format_date( $wp_last_activity ) ); |
| 159 |
} else { |
| 160 |
_e( 'No activity yet', 'wpforo' ); |
| 161 |
} |
| 162 |
?> |
| 163 |
</div> |
| 164 |
</div> |
| 165 |
|
| 166 |
<div class="wpforo-ai-wp-status-item wpforo-ai-wp-stat-large"> |
| 167 |
<div class="status-label"><?php _e( 'Remaining Credits', 'wpforo' ); ?></div> |
| 168 |
<div class="status-value" id="wp-remaining-credits"> |
| 169 |
<?php echo number_format( $remaining_credits ); ?> |
| 170 |
</div> |
| 171 |
</div> |
| 172 |
</div> |
| 173 |
</div> |
| 174 |
</div> |
| 175 |
|
| 176 |
<!-- WordPress Content Indexing Box --> |
| 177 |
<div class="wpforo-ai-box wpforo-ai-wordpress-indexing-box"> |
| 178 |
<div class="wpforo-ai-box-header"> |
| 179 |
<h2> |
| 180 |
<span class="dashicons dashicons-wordpress-alt"></span> |
| 181 |
<?php _e( 'WordPress Content Indexing', 'wpforo' ); ?> |
| 182 |
</h2> |
| 183 |
<div class="wpforo-ai-header-actions"> |
| 184 |
<!-- Image indexing temporarily disabled - feature not yet implemented --> |
| 185 |
<label class="wpforo-ai-auto-index-toggle" style="display:none;" title="<?php esc_attr_e( 'Include images in indexing (Business/Enterprise). Posts with images will consume +1 credit.', 'wpforo' ); ?>"> |
| 186 |
<span class="wpforo-ai-auto-index-label"> |
| 187 |
<?php _e( 'Index Images', 'wpforo' ); ?> |
| 188 |
</span> |
| 189 |
<div class="wpforo-ai-switch"> |
| 190 |
<input type="checkbox" id="wpforo-ai-wp-image-indexing" name="ai_wp_image_indexing_enabled" value="1" <?php checked( $wp_image_indexing_enabled ); ?> data-option-name="ai_wp_image_indexing_enabled"> |
| 191 |
<span class="wpforo-ai-switch-slider"></span> |
| 192 |
</div> |
| 193 |
</label> |
| 194 |
<!-- Auto-indexing temporarily disabled - will be improved in future release --> |
| 195 |
<label class="wpforo-ai-auto-index-toggle" style="display:none;" title="<?php esc_attr_e( 'Automatically index new and updated WordPress content', 'wpforo' ); ?>"> |
| 196 |
<span class="wpforo-ai-auto-index-label"><?php _e( 'Automatically index new content', 'wpforo' ); ?></span> |
| 197 |
<div class="wpforo-ai-switch"> |
| 198 |
<input type="checkbox" id="wpforo-ai-wp-auto-indexing" name="ai_wp_auto_indexing_enabled" value="1" <?php checked( $wp_auto_indexing_enabled ); ?> data-option-name="ai_wp_auto_indexing_enabled"> |
| 199 |
<span class="wpforo-ai-switch-slider"></span> |
| 200 |
</div> |
| 201 |
</label> |
| 202 |
</div> |
| 203 |
</div> |
| 204 |
<div class="wpforo-ai-box-body"> |
| 205 |
<p class="wpforo-ai-description"> |
| 206 |
<?php _e( 'Index WordPress posts, pages, and custom post types to enable AI-powered search across all your site content. This works alongside forum content indexing.', 'wpforo' ); ?> |
| 207 |
</p> |
| 208 |
|
| 209 |
<!-- WordPress Content Stats --> |
| 210 |
<div class="wpforo-ai-wp-stats"> |
| 211 |
<div class="rag-stat-item"> |
| 212 |
<div class="stat-icon"> |
| 213 |
<span class="dashicons dashicons-admin-page"></span> |
| 214 |
</div> |
| 215 |
<div class="stat-info"> |
| 216 |
<div class="stat-value" id="wp-total-content"><?php echo number_format( $wp_total_content ); ?></div> |
| 217 |
<div class="stat-label"><?php _e( 'Total WordPress Content', 'wpforo' ); ?></div> |
| 218 |
</div> |
| 219 |
</div> |
| 220 |
<div class="rag-stat-item"> |
| 221 |
<div class="stat-icon"> |
| 222 |
<span class="dashicons dashicons-database-view"></span> |
| 223 |
</div> |
| 224 |
<div class="stat-info"> |
| 225 |
<div class="stat-value" id="wp-total-indexed"><?php echo number_format( $wp_initial_indexed ); ?></div> |
| 226 |
<div class="stat-label"><?php _e( 'Total Indexed', 'wpforo' ); ?></div> |
| 227 |
</div> |
| 228 |
</div> |
| 229 |
<div class="rag-stat-item"> |
| 230 |
<div class="stat-icon"> |
| 231 |
<span class="dashicons dashicons-chart-pie"></span> |
| 232 |
</div> |
| 233 |
<div class="stat-info"> |
| 234 |
<?php |
| 235 |
$wp_percentage = $wp_total_content > 0 ? round( ( $wp_initial_indexed / $wp_total_content ) * 100, 1 ) : 0; |
| 236 |
?> |
| 237 |
<div class="stat-value" id="wp-indexed-percentage"><?php echo $wp_percentage; ?>%</div> |
| 238 |
<div class="stat-label"><?php _e( 'Coverage', 'wpforo' ); ?></div> |
| 239 |
</div> |
| 240 |
</div> |
| 241 |
</div> |
| 242 |
|
| 243 |
<?php if ( empty( $wp_post_types ) ) : ?> |
| 244 |
<div class="wpforo-ai-notice wpforo-ai-notice-warning"> |
| 245 |
<span class="dashicons dashicons-warning"></span> |
| 246 |
<p><?php _e( 'No public post types with content found.', 'wpforo' ); ?></p> |
| 247 |
</div> |
| 248 |
<?php else : ?> |
| 249 |
|
| 250 |
<div class="wpforo-ai-ingest-grid wpforo-ai-wp-ingest-grid"> |
| 251 |
<!-- Taxonomy Selection Column --> |
| 252 |
<div class="wpforo-ai-ingest-column"> |
| 253 |
<h3><?php _e( 'Index by Categories/Taxonomies', 'wpforo' ); ?></h3> |
| 254 |
<p class="description"> |
| 255 |
<?php _e( 'Select a taxonomy and term to index all content in that category.', 'wpforo' ); ?> |
| 256 |
</p> |
| 257 |
|
| 258 |
<form class="wpforo-ai-wp-taxonomy-form"> |
| 259 |
<?php wp_nonce_field( 'wpforo_admin_ajax', 'security' ); ?> |
| 260 |
|
| 261 |
<!-- Date Range Filter --> |
| 262 |
<div class="form-row wpforo-ai-date-range"> |
| 263 |
<label><?php _e( 'Date Range (optional)', 'wpforo' ); ?></label> |
| 264 |
<div class="wpforo-ai-date-inputs"> |
| 265 |
<input type="date" id="wp-tax-date-from" name="date_from" class="regular-text"> |
| 266 |
<span class="wpforo-ai-date-separator"><?php _e( 'to', 'wpforo' ); ?></span> |
| 267 |
<input type="date" id="wp-tax-date-to" name="date_to" class="regular-text"> |
| 268 |
</div> |
| 269 |
<p class="description"> |
| 270 |
<?php _e( 'Filter by content publication date within the selected category.', 'wpforo' ); ?> |
| 271 |
</p> |
| 272 |
</div> |
| 273 |
|
| 274 |
<div class="form-row"> |
| 275 |
<label for="wp-taxonomy-select"> |
| 276 |
<?php _e( 'Taxonomy', 'wpforo' ); ?> |
| 277 |
</label> |
| 278 |
<select id="wp-taxonomy-select" name="taxonomy" class="regular-text"> |
| 279 |
<option value=""><?php _e( 'Select a taxonomy...', 'wpforo' ); ?></option> |
| 280 |
<?php |
| 281 |
// Get taxonomies for the first post type by default |
| 282 |
$first_type = reset( $wp_post_types ); |
| 283 |
if ( $first_type && isset( WPF()->ai_wp_indexer ) ) { |
| 284 |
$taxonomies = WPF()->ai_wp_indexer->get_taxonomies_for_post_type( $first_type['name'] ); |
| 285 |
foreach ( $taxonomies as $tax ) : |
| 286 |
?> |
| 287 |
<option value="<?php echo esc_attr( $tax['name'] ); ?>"> |
| 288 |
<?php echo esc_html( $tax['label'] ); ?> (<?php echo number_format( $tax['term_count'] ); ?> terms) |
| 289 |
</option> |
| 290 |
<?php |
| 291 |
endforeach; |
| 292 |
} |
| 293 |
?> |
| 294 |
</select> |
| 295 |
</div> |
| 296 |
|
| 297 |
<div class="form-row"> |
| 298 |
<label> |
| 299 |
<?php _e( 'Terms/Categories', 'wpforo' ); ?> |
| 300 |
</label> |
| 301 |
<div id="wp-terms-container" class="wpforo-ai-terms-container"> |
| 302 |
<div class="wpforo-ai-terms-placeholder"> |
| 303 |
<?php _e( 'Select a taxonomy first to load terms...', 'wpforo' ); ?> |
| 304 |
</div> |
| 305 |
</div> |
| 306 |
<div id="wp-terms-actions" class="wpforo-ai-terms-actions" style="display: none;"> |
| 307 |
<button type="button" class="button button-small wpforo-ai-wp-select-all-terms"> |
| 308 |
<?php _e( 'Select All', 'wpforo' ); ?> |
| 309 |
</button> |
| 310 |
<button type="button" class="button button-small wpforo-ai-wp-deselect-all-terms"> |
| 311 |
<?php _e( 'Deselect All', 'wpforo' ); ?> |
| 312 |
</button> |
| 313 |
</div> |
| 314 |
</div> |
| 315 |
|
| 316 |
<div class="form-actions"> |
| 317 |
<button type="submit" class="button button-primary button-large wpforo-ai-wp-index-taxonomy" disabled> |
| 318 |
<span class="dashicons dashicons-upload"></span> |
| 319 |
<?php _e( 'Index Selected Terms', 'wpforo' ); ?> |
| 320 |
</button> |
| 321 |
</div> |
| 322 |
</form> |
| 323 |
</div> |
| 324 |
|
| 325 |
<!-- Custom Indexing Column --> |
| 326 |
<div class="wpforo-ai-ingest-column wpforo-ai-wp-custom-index"> |
| 327 |
<h3><?php _e( 'Index by Content Type', 'wpforo' ); ?></h3> |
| 328 |
<p class="description"> |
| 329 |
<?php _e( 'Select content types and optionally filter by date range.', 'wpforo' ); ?> |
| 330 |
</p> |
| 331 |
|
| 332 |
<form class="wpforo-ai-wp-custom-form"> |
| 333 |
<?php wp_nonce_field( 'wpforo_admin_ajax', 'security' ); ?> |
| 334 |
|
| 335 |
<!-- Date Range Filter --> |
| 336 |
<div class="form-row wpforo-ai-date-range"> |
| 337 |
<label><?php _e( 'Date Range (optional)', 'wpforo' ); ?></label> |
| 338 |
<div class="wpforo-ai-date-inputs"> |
| 339 |
<input type="date" id="wp-date-from" name="date_from" class="regular-text"> |
| 340 |
<span class="wpforo-ai-date-separator"><?php _e( 'to', 'wpforo' ); ?></span> |
| 341 |
<input type="date" id="wp-date-to" name="date_to" class="regular-text"> |
| 342 |
</div> |
| 343 |
<p class="description"> |
| 344 |
<?php _e( 'Leave empty to index all content of selected types.', 'wpforo' ); ?> |
| 345 |
</p> |
| 346 |
</div> |
| 347 |
|
| 348 |
<!-- Content Types Selection --> |
| 349 |
<div class="form-row"> |
| 350 |
<label><?php _e( 'Content Types', 'wpforo' ); ?></label> |
| 351 |
<p class="description"> |
| 352 |
<?php _e( 'Not all posts may be indexed. Content generated dynamically by shortcodes or page builders may not contain indexable text. Posts with very short content (less than 10 characters after stripping HTML and shortcodes) are also skipped. The indexed count may differ from the total if such content exists.', 'wpforo' ); ?> |
| 353 |
</p> |
| 354 |
<div class="wpforo-ai-wp-types-grid wpforo-ai-wp-types-compact"> |
| 355 |
<?php foreach ( $wp_post_types as $type ) : ?> |
| 356 |
<label class="wpforo-ai-wp-type-item"> |
| 357 |
<input type="checkbox" |
| 358 |
name="wp_post_types[]" |
| 359 |
value="<?php echo esc_attr( $type['name'] ); ?>" |
| 360 |
data-count="<?php echo esc_attr( $type['count'] ); ?>" |
| 361 |
class="wpforo-ai-wp-type-checkbox"> |
| 362 |
<span class="type-label"><?php echo esc_html( $type['label'] ); ?></span> |
| 363 |
<span class="type-count">(<?php echo number_format( $type['count'] ); ?>)</span> |
| 364 |
<?php |
| 365 |
$type_key = 'wp_' . $type['name']; |
| 366 |
$type_indexed_count = 0; |
| 367 |
if ( $wp_initial_status && ! is_wp_error( $wp_initial_status ) && isset( $wp_initial_status['by_type'][ $type_key ]['indexed'] ) ) { |
| 368 |
$type_indexed_count = (int) $wp_initial_status['by_type'][ $type_key ]['indexed']; |
| 369 |
} |
| 370 |
?> |
| 371 |
<span class="type-indexed" id="wp-indexed-<?php echo esc_attr( $type['name'] ); ?>"> |
| 372 |
<span class="indexed-count"><?php echo (int) $type_indexed_count; ?></span> <?php _e( 'indexed', 'wpforo' ); ?> |
| 373 |
</span> |
| 374 |
</label> |
| 375 |
<?php endforeach; ?> |
| 376 |
</div> |
| 377 |
</div> |
| 378 |
|
| 379 |
<div class="form-actions"> |
| 380 |
<button type="submit" class="button button-primary button-large wpforo-ai-wp-index-custom"> |
| 381 |
<span class="dashicons dashicons-upload"></span> |
| 382 |
<?php _e( 'Index Selected Content', 'wpforo' ); ?> |
| 383 |
</button> |
| 384 |
</div> |
| 385 |
</form> |
| 386 |
|
| 387 |
<div class="wpforo-ai-section-divider wpforo-ai-section-divider-small"> |
| 388 |
<span><?php _e( 'Or index by specific IDs:', 'wpforo' ); ?></span> |
| 389 |
</div> |
| 390 |
|
| 391 |
<!-- Specific IDs Form (Independent) --> |
| 392 |
<form class="wpforo-ai-wp-ids-form"> |
| 393 |
<?php wp_nonce_field( 'wpforo_admin_ajax', 'security' ); ?> |
| 394 |
|
| 395 |
<div class="form-row"> |
| 396 |
<label for="wp-post-ids"> |
| 397 |
<?php _e( 'Post/Page IDs', 'wpforo' ); ?> |
| 398 |
</label> |
| 399 |
<textarea id="wp-post-ids" name="post_ids" class="large-text" rows="2" placeholder="<?php esc_attr_e( 'e.g., 123, 456, 789', 'wpforo' ); ?>"></textarea> |
| 400 |
<p class="description"> |
| 401 |
<?php _e( 'Comma-separated post IDs. Indexes regardless of content type or date.', 'wpforo' ); ?> |
| 402 |
</p> |
| 403 |
</div> |
| 404 |
|
| 405 |
<div class="form-actions"> |
| 406 |
<button type="submit" class="button button-large button-secondary wpforo-ai-wp-index-ids"> |
| 407 |
<span class="dashicons dashicons-upload"></span> |
| 408 |
<?php _e( 'Index by IDs', 'wpforo' ); ?> |
| 409 |
</button> |
| 410 |
</div> |
| 411 |
</form> |
| 412 |
</div> |
| 413 |
</div> |
| 414 |
|
| 415 |
<!-- Quick Actions --> |
| 416 |
<div class="wpforo-ai-wp-quick-actions"> |
| 417 |
<button type="button" class="button wpforo-ai-wp-cleanup-session" data-confirm="<?php esc_attr_e( 'Reset stuck WordPress indexing session? This clears the pending post queue, cron jobs and cached status. Already-indexed posts are NOT affected.', 'wpforo' ); ?>" title="<?php esc_attr_e( 'Clears pending WordPress post/page indexing queue, WP-Cron jobs and status cache. Use this if WordPress indexing is stuck on "Indexing..." but nothing is progressing. Works for both local and cloud storage modes. Does not delete any indexed data.', 'wpforo' ); ?>"> |
| 418 |
<span class="dashicons dashicons-update-alt"></span> |
| 419 |
<?php _e( 'Cleanup Indexing Session', 'wpforo' ); ?> |
| 420 |
</button> |
| 421 |
<button type="button" class="button button-link-delete wpforo-ai-wp-clear-index" data-confirm="<?php esc_attr_e( 'This will remove all WordPress content from the AI index. Continue?', 'wpforo' ); ?>"> |
| 422 |
<span class="dashicons dashicons-trash"></span> |
| 423 |
<?php _e( 'Clear WordPress Index', 'wpforo' ); ?> |
| 424 |
</button> |
| 425 |
</div> |
| 426 |
<?php endif; ?> |
| 427 |
</div> |
| 428 |
</div> |
| 429 |
|
| 430 |
</div> |
| 431 |
<?php |
| 432 |
} |
| 433 |
|