prefix . 'aisearch_logs'; $wpdb->query( "DROP TABLE IF EXISTS {$ai_search_log_table}" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery // Scheduled retention cleanup. $ai_search_cron = wp_next_scheduled( 'ai_search_purge_logs' ); if ( $ai_search_cron ) { wp_unschedule_event( $ai_search_cron, 'ai_search_purge_logs' ); } // Settings. $ai_search_options = [ 'ai_search_provider', 'ai_search_api_key', 'ai_search_service_token', 'ai_search_openai_model', 'ai_search_similarity_threshold', 'ai_search_term_embeddings_enabled', 'ai_search_term_weight', 'ai_search_disabled_taxonomies', 'ai_search_woocommerce_fields', 'ai_search_setup_completed', 'ai_search_show_setup_wizard', 'ai_search_badge_public', 'ai_search_registered_origin', 'ai_search_woo_welcome_dismissed', 'ai_search_blocks_notice_dismissed', 'ai_search_logging_enabled', 'ai_search_log_retention_days', 'ai_search_log_db_version', // Removed in 1.28.0 but may linger on long-lived installs. 'ai_search_hybrid_enabled', 'ai_search_hybrid_balance', ]; foreach ( $ai_search_options as $ai_search_option ) { delete_option( $ai_search_option ); } // Per-post-type custom field selections (ai_search_custom_fields_{post_type}). $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'ai_search_custom_fields_%'" ); // Plugin transients. $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_ai_search_%' OR option_name LIKE '_transient_timeout_ai_search_%' OR option_name LIKE '_transient_ai_service_%' OR option_name LIKE '_transient_timeout_ai_service_%'" );