true ], 'names' ); foreach ( $post_types as $post_type ) { add_meta_box( 'ai_search_status', __( 'AI Search Status', 'ai-search' ), [ $this, 'render_meta_box' ], $post_type, 'side', 'default' ); } } /** * Render meta box content */ public function render_meta_box( $post ) { // Check if post has embedding $embedding = get_post_meta( $post->ID, '_ai_search_embedding', true ); $has_embedding = ! empty( $embedding ); // Get the AI Search instance to generate preview content $ai_search = AI_Search::get_instance(); ?>
__( 'Poor', 'ai-search' ), 'message' => __( 'Very limited content. Add more text, descriptions, or configure custom fields to improve search accuracy.', 'ai-search' ), 'bg_color' => '#f8d7da', 'border_color' => '#dc3545', 'badge_color' => '#dc3545', 'word_count' => $word_count, 'char_count' => $char_count, ]; } elseif ( $word_count < 150 ) { return [ 'label' => __( 'Fair', 'ai-search' ), 'message' => __( 'Basic content available. Consider adding more details or custom fields for better search results.', 'ai-search' ), 'bg_color' => '#fff3cd', 'border_color' => '#ffc107', 'badge_color' => '#ffc107', 'word_count' => $word_count, 'char_count' => $char_count, ]; } elseif ( $word_count < 300 ) { return [ 'label' => __( 'Good', 'ai-search' ), 'message' => __( 'Solid content for AI search. The embedding should provide accurate search results.', 'ai-search' ), 'bg_color' => '#d1ecf1', 'border_color' => '#17a2b8', 'badge_color' => '#17a2b8', 'word_count' => $word_count, 'char_count' => $char_count, ]; } else { return [ 'label' => __( 'Excellent', 'ai-search' ), 'message' => __( 'Rich, detailed content. This will generate a high-quality embedding for precise search results.', 'ai-search' ), 'bg_color' => '#d4edda', 'border_color' => '#28a745', 'badge_color' => '#28a745', 'word_count' => $word_count, 'char_count' => $char_count, ]; } } /** * Get preview of content that will be used for embedding */ private function get_embedding_preview( $post_id ) { $post = get_post( $post_id ); if ( ! $post ) { return ''; } // Get title $content = sanitize_text_field( $post->post_title ); // Get post content (stripped of HTML and shortcodes) $post_content = wp_strip_all_tags( strip_shortcodes( $post->post_content ) ); $post_content = preg_replace( '/\s+/', ' ', trim( $post_content ) ); $content .= ' ' . $post_content; // Get custom fields $custom_fields = get_option( 'ai_search_custom_fields_' . $post->post_type, [] ); if ( ! empty( $custom_fields ) && is_array( $custom_fields ) ) { foreach ( $custom_fields as $field_key ) { $field_value = get_post_meta( $post_id, $field_key, true ); if ( ! empty( $field_value ) && is_string( $field_value ) ) { $clean_value = wp_strip_all_tags( strip_shortcodes( $field_value ) ); $clean_value = preg_replace( '/\s+/', ' ', trim( $clean_value ) ); if ( ! empty( $clean_value ) ) { $content .= ' ' . $clean_value; } } } } // Get WooCommerce fields if applicable if ( $post->post_type === 'product' && class_exists( 'WooCommerce' ) ) { $woo_fields = get_option( 'ai_search_woocommerce_fields', [] ); if ( ! empty( $woo_fields ) && is_array( $woo_fields ) ) { $product = wc_get_product( $post_id ); if ( $product ) { foreach ( $woo_fields as $woo_field ) { switch ( $woo_field ) { case 'short_description': $desc = $product->get_short_description(); if ( ! empty( $desc ) ) { $desc = wp_strip_all_tags( strip_shortcodes( $desc ) ); $desc = preg_replace( '/\s+/', ' ', trim( $desc ) ); $content .= ' ' . $desc; } break; case 'categories': $categories = wp_get_post_terms( $post_id, 'product_cat', [ 'fields' => 'names' ] ); if ( ! is_wp_error( $categories ) && ! empty( $categories ) ) { $content .= ' ' . implode( ' ', $categories ); } break; case 'tags': $tags = wp_get_post_terms( $post_id, 'product_tag', [ 'fields' => 'names' ] ); if ( ! is_wp_error( $tags ) && ! empty( $tags ) ) { $content .= ' ' . implode( ' ', $tags ); } break; case 'sku': $sku = $product->get_sku(); if ( ! empty( $sku ) ) { $content .= ' ' . $sku; } break; } } } } } return trim( $content ); } /** * AJAX handler for regenerate embedding request */ public function ajax_regenerate_embedding() { $post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0; if ( ! $post_id ) { wp_send_json_error( [ 'message' => __( 'Invalid post ID', 'ai-search' ) ] ); } check_ajax_referer( 'ai_search_regenerate_' . $post_id, 'nonce' ); if ( ! current_user_can( 'edit_post', $post_id ) ) { wp_send_json_error( [ 'message' => __( 'You do not have permission to edit this post', 'ai-search' ) ] ); } // Check if post is published $post = get_post( $post_id ); if ( ! $post || $post->post_status !== 'publish' ) { wp_send_json_error( [ 'message' => __( 'Only published posts can have embeddings generated.', 'ai-search' ) ] ); } // Delete existing embedding to force regeneration delete_post_meta( $post_id, '_ai_search_embedding' ); // Generate embedding $ai_search = AI_Search::get_instance(); $result = $ai_search->generate_embedding( $post_id ); if ( ! is_wp_error( $result ) && ! empty( get_post_meta( $post_id, '_ai_search_embedding', true ) ) ) { wp_send_json_success( [ 'message' => __( 'Post synced with AI successfully!', 'ai-search' ) ] ); } $reason = is_wp_error( $result ) ? $result->get_error_message() : __( 'The AI provider did not return an embedding.', 'ai-search' ); wp_send_json_error( [ 'code' => is_wp_error( $result ) ? $result->get_error_code() : 'provider_error', /* translators: %s: reason the embedding could not be generated */ 'message' => sprintf( __( 'Failed to sync with AI: %s', 'ai-search' ), $reason ), ] ); } /** * Enqueue scripts for meta box */ public function enqueue_scripts( $hook ) { if ( ! in_array( $hook, [ 'post.php', 'post-new.php' ] ) ) { return; } // Add AJAX handler for regenerate button (vanilla JS) ?>