PluginProbe
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent / 3.5.4
SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent v3.5.4
3.5.4 3.5.3 3.5.2 3.5.1 3.4.9 3.5.0 3.4.8 3.4.7 trunk 2.3.1 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6
← All changes | class-wpsc-installation.php +463 -100 3.5.0 → 3.5.4 View file →
@@ -232,8 +232,9 @@
232 232 source VARCHAR(200) NOT NULL,
233 233 source_id BIGINT NOT NULL DEFAULT 0,
234 234 ticket_id BIGINT NOT NULL DEFAULT 0,
235 235 customer_id BIGINT NOT NULL DEFAULT 0,
236 + uploaded_by VARCHAR(64) NOT NULL DEFAULT '',
236 237 PRIMARY KEY (id)
237 238 ) $collate;
238 239 CREATE TABLE {$wpdb->prefix}psmsc_agents (
239 240 id BIGINT NOT NULL AUTO_INCREMENT,
@@ -322,8 +323,70 @@
322 323 color VARCHAR(50) NOT NULL,
323 324 bg_color VARCHAR(50) NOT NULL,
324 325 PRIMARY KEY (id)
325 326 ) $collate;
327 + CREATE TABLE {$wpdb->prefix}psmsc_ai_logs (
328 + id BIGINT NOT NULL AUTO_INCREMENT,
329 + customer BIGINT NOT NULL,
330 + ticket BIGINT NOT NULL,
331 + provider VARCHAR(100) NOT NULL,
332 + model VARCHAR(100) NOT NULL,
333 + feature VARCHAR(50) NOT NULL,
334 + tokens INT NOT NULL,
335 + prompt LONGTEXT NOT NULL,
336 + date_created DATETIME NOT NULL,
337 + PRIMARY KEY (id),
338 + KEY customer (customer),
339 + KEY date_created (date_created)
340 + ) $collate;
341 + CREATE TABLE {$wpdb->prefix}psmsc_ai_training (
342 + id BIGINT NOT NULL AUTO_INCREMENT,
343 + status VARCHAR(20) NOT NULL,
344 + provider VARCHAR(50) NOT NULL,
345 + source VARCHAR(50) NOT NULL,
346 + source_id BIGINT NOT NULL,
347 + doc_source VARCHAR(255) NULL,
348 + name VARCHAR(255) NOT NULL,
349 + file_path VARCHAR(500) NOT NULL,
350 + provider_file_id VARCHAR(255) NULL,
351 + meta_data LONGTEXT NULL,
352 + post_updated_on DATETIME NOT NULL,
353 + date_updated DATETIME NOT NULL,
354 + date_created DATETIME NOT NULL,
355 + PRIMARY KEY (id),
356 + INDEX idx_status (status),
357 + INDEX idx_source (source),
358 + INDEX idx_status_source (status, source)
359 + ) $collate;
360 + CREATE TABLE {$wpdb->prefix}psmsc_acb_sessions (
361 + id BIGINT NOT NULL AUTO_INCREMENT,
362 + session_id CHAR(36) NOT NULL,
363 + visitor_id CHAR(36) NOT NULL,
364 + subject LONGTEXT NULL,
365 + provider VARCHAR(20) NOT NULL DEFAULT '',
366 + reaction tinyint(1) NULL,
367 + ticket_id BIGINT NULL,
368 + status tinyint(1) NOT NULL,
369 + token_count INT UNSIGNED NOT NULL,
370 + last_activity DATETIME NOT NULL,
371 + date_created DATETIME NOT NULL,
372 + PRIMARY KEY (id),
373 + UNIQUE KEY session_id (session_id),
374 + KEY visitor_id (visitor_id),
375 + KEY status (status),
376 + KEY date_created (date_created)
377 + ) $collate;
378 + CREATE TABLE {$wpdb->prefix}psmsc_acb_messages (
379 + id BIGINT NOT NULL AUTO_INCREMENT,
380 + session_id CHAR(36) NOT NULL,
381 + sender VARCHAR(10) NOT NULL,
382 + message LONGTEXT NULL,
383 + token_count INT UNSIGNED NOT NULL,
384 + date_created DATETIME NOT NULL,
385 + PRIMARY KEY (id),
386 + KEY session_id (session_id),
387 + KEY session_messages (session_id, date_created)
388 + ) $collate;
326 389 ";
327 390
328 391 dbDelta( $tables );
329 392
@@ -335,8 +398,24 @@
335 398 // Copy structure of psmsc_thread table to psmsc_archived_threads table.
336 399 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}psmsc_archived_threads'" ) !== "{$wpdb->prefix}psmsc_archived_threads" ) {
337 400 $wpdb->query( "CREATE TABLE {$wpdb->prefix}psmsc_archived_threads LIKE {$wpdb->prefix}psmsc_threads" );
338 401 }
402 +
403 + // AI assistant feature: add 'ticket_summary' column to tickets and archived tickets table.
404 + $column_exists = $wpdb->get_results( "SHOW COLUMNS FROM {$wpdb->prefix}psmsc_tickets LIKE 'ticket_summary'" );
405 + if ( empty( $column_exists ) ) {
406 + $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_tickets ADD ticket_summary TEXT NULL" );
407 + }
408 + $column_exists = $wpdb->get_results( "SHOW COLUMNS FROM {$wpdb->prefix}psmsc_archived_tickets LIKE 'ticket_summary'" );
409 + if ( empty( $column_exists ) ) {
410 + $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_archived_tickets ADD ticket_summary TEXT NULL" );
411 + }
412 +
413 + // Attachment ownership: add 'uploaded_by' column to attachments table.
414 + $column_exists = $wpdb->get_results( "SHOW COLUMNS FROM {$wpdb->prefix}psmsc_attachments LIKE 'uploaded_by'" );
415 + if ( empty( $column_exists ) ) {
416 + $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_attachments ADD uploaded_by VARCHAR(64) NOT NULL DEFAULT ''" );
417 + }
339 418 }
340 419
341 420 /**
342 421 * First time installation
@@ -745,104 +824,110 @@
745 824 )
746 825 );
747 826 $string_translations[ 'wpsc-cf-name-' . $wpdb->insert_id ] = $name;
748 827
749 - // Insert default category.
750 - $name = __( 'General', 'supportcandy' );
751 - $wpdb->insert(
752 - $wpdb->prefix . 'psmsc_categories',
753 - array(
754 - 'name' => $name,
755 - 'load_order' => 1,
756 - )
757 - );
758 - $string_translations[ 'wpsc-category-' . $wpdb->insert_id ] = $name;
828 + // Insert default category, guarded against re-running initial_setup().
829 + if ( ! $wpdb->get_var( "SELECT id FROM {$wpdb->prefix}psmsc_categories LIMIT 1" ) ) {
830 + $name = __( 'General', 'supportcandy' );
831 + $wpdb->insert(
832 + $wpdb->prefix . 'psmsc_categories',
833 + array(
834 + 'name' => $name,
835 + 'load_order' => 1,
836 + )
837 + );
838 + $string_translations[ 'wpsc-category-' . $wpdb->insert_id ] = $name;
839 + }
759 840
760 - // Insert default statuses.
761 - $name = __( 'Open', 'supportcandy' );
762 - $wpdb->insert(
763 - $wpdb->prefix . 'psmsc_statuses',
764 - array(
765 - 'name' => $name,
766 - 'color' => '#ec1010',
767 - 'bg_color' => '#ffe7e1',
768 - 'load_order' => 1,
769 - )
770 - );
771 - $string_translations[ 'wpsc-status-' . $wpdb->insert_id ] = $name;
841 + // Insert default statuses, guarded against re-running initial_setup().
842 + if ( ! $wpdb->get_var( "SELECT id FROM {$wpdb->prefix}psmsc_statuses LIMIT 1" ) ) {
843 + $name = __( 'Open', 'supportcandy' );
844 + $wpdb->insert(
845 + $wpdb->prefix . 'psmsc_statuses',
846 + array(
847 + 'name' => $name,
848 + 'color' => '#ec1010',
849 + 'bg_color' => '#ffe7e1',
850 + 'load_order' => 1,
851 + )
852 + );
853 + $string_translations[ 'wpsc-status-' . $wpdb->insert_id ] = $name;
772 854
773 - $name = __( 'Awaiting customer reply', 'supportcandy' );
774 - $wpdb->insert(
775 - $wpdb->prefix . 'psmsc_statuses',
776 - array(
777 - 'name' => $name,
778 - 'color' => '#8222E6',
779 - 'bg_color' => '#E9D3FF',
780 - 'load_order' => 2,
781 - )
782 - );
783 - $string_translations[ 'wpsc-status-' . $wpdb->insert_id ] = $name;
855 + $name = __( 'Awaiting customer reply', 'supportcandy' );
856 + $wpdb->insert(
857 + $wpdb->prefix . 'psmsc_statuses',
858 + array(
859 + 'name' => $name,
860 + 'color' => '#8222E6',
861 + 'bg_color' => '#E9D3FF',
862 + 'load_order' => 2,
863 + )
864 + );
865 + $string_translations[ 'wpsc-status-' . $wpdb->insert_id ] = $name;
784 866
785 - $name = __( 'Awaiting agent reply', 'supportcandy' );
786 - $wpdb->insert(
787 - $wpdb->prefix . 'psmsc_statuses',
788 - array(
789 - 'name' => $name,
790 - 'color' => '#EB961C',
791 - 'bg_color' => '#FFEBCE',
792 - 'load_order' => 3,
793 - )
794 - );
795 - $string_translations[ 'wpsc-status-' . $wpdb->insert_id ] = $name;
867 + $name = __( 'Awaiting agent reply', 'supportcandy' );
868 + $wpdb->insert(
869 + $wpdb->prefix . 'psmsc_statuses',
870 + array(
871 + 'name' => $name,
872 + 'color' => '#EB961C',
873 + 'bg_color' => '#FFEBCE',
874 + 'load_order' => 3,
875 + )
876 + );
877 + $string_translations[ 'wpsc-status-' . $wpdb->insert_id ] = $name;
796 878
797 - $name = __( 'Closed', 'supportcandy' );
798 - $wpdb->insert(
799 - $wpdb->prefix . 'psmsc_statuses',
800 - array(
801 - 'name' => $name,
802 - 'color' => '#22940d',
803 - 'bg_color' => '#c1ffcf',
804 - 'load_order' => 4,
805 - )
806 - );
807 - $string_translations[ 'wpsc-status-' . $wpdb->insert_id ] = $name;
879 + $name = __( 'Closed', 'supportcandy' );
880 + $wpdb->insert(
881 + $wpdb->prefix . 'psmsc_statuses',
882 + array(
883 + 'name' => $name,
884 + 'color' => '#22940d',
885 + 'bg_color' => '#c1ffcf',
886 + 'load_order' => 4,
887 + )
888 + );
889 + $string_translations[ 'wpsc-status-' . $wpdb->insert_id ] = $name;
890 + }
808 891
809 - // Insert default priorities.
810 - $name = __( 'Low', 'supportcandy' );
811 - $wpdb->insert(
812 - $wpdb->prefix . 'psmsc_priorities',
813 - array(
814 - 'name' => $name,
815 - 'color' => '#22940d',
816 - 'bg_color' => '#c1ffcf',
817 - 'load_order' => 1,
818 - )
819 - );
820 - $string_translations[ 'wpsc-priority-' . $wpdb->insert_id ] = $name;
892 + // Insert default priorities, guarded against re-running initial_setup().
893 + if ( ! $wpdb->get_var( "SELECT id FROM {$wpdb->prefix}psmsc_priorities LIMIT 1" ) ) {
894 + $name = __( 'Low', 'supportcandy' );
895 + $wpdb->insert(
896 + $wpdb->prefix . 'psmsc_priorities',
897 + array(
898 + 'name' => $name,
899 + 'color' => '#22940d',
900 + 'bg_color' => '#c1ffcf',
901 + 'load_order' => 1,
902 + )
903 + );
904 + $string_translations[ 'wpsc-priority-' . $wpdb->insert_id ] = $name;
821 905
822 - $name = __( 'Medium', 'supportcandy' );
823 - $wpdb->insert(
824 - $wpdb->prefix . 'psmsc_priorities',
825 - array(
826 - 'name' => $name,
827 - 'color' => '#EB961C',
828 - 'bg_color' => '#FFEBCE',
829 - 'load_order' => 2,
830 - )
831 - );
832 - $string_translations[ 'wpsc-priority-' . $wpdb->insert_id ] = $name;
906 + $name = __( 'Medium', 'supportcandy' );
907 + $wpdb->insert(
908 + $wpdb->prefix . 'psmsc_priorities',
909 + array(
910 + 'name' => $name,
911 + 'color' => '#EB961C',
912 + 'bg_color' => '#FFEBCE',
913 + 'load_order' => 2,
914 + )
915 + );
916 + $string_translations[ 'wpsc-priority-' . $wpdb->insert_id ] = $name;
833 917
834 - $name = __( 'High', 'supportcandy' );
835 - $wpdb->insert(
836 - $wpdb->prefix . 'psmsc_priorities',
837 - array(
838 - 'name' => $name,
839 - 'color' => '#ec1010',
840 - 'bg_color' => '#ffe7e1',
841 - 'load_order' => 3,
842 - )
843 - );
844 - $string_translations[ 'wpsc-priority-' . $wpdb->insert_id ] = $name;
918 + $name = __( 'High', 'supportcandy' );
919 + $wpdb->insert(
920 + $wpdb->prefix . 'psmsc_priorities',
921 + array(
922 + 'name' => $name,
923 + 'color' => '#ec1010',
924 + 'bg_color' => '#ffe7e1',
925 + 'load_order' => 3,
926 + )
927 + );
928 + $string_translations[ 'wpsc-priority-' . $wpdb->insert_id ] = $name;
929 + }
845 930
846 931 // company working hrs.
847 932 for ( $i = 1; $i <= 7; $i++ ) {
848 933 $wpdb->insert(
@@ -1734,15 +1819,8 @@
1734 1819 'z-index' => 900000000,
1735 1820 )
1736 1821 );
1737 1822 update_option(
1738 - 'wpsc-ap-agent-collision',
1739 - array(
1740 - 'header-bg-color' => '#e6e6e6',
1741 - 'header-text-color' => '#2c3e50',
1742 - )
1743 - );
1744 - update_option(
1745 1823 'wpsc-ap-ticket-list',
1746 1824 array(
1747 1825 'list-header-background-color' => '#2c3e50',
1748 1826 'list-header-text-color' => '#fff',
@@ -1767,12 +1845,12 @@
1767 1845 // dashboard general setting.
1768 1846 update_option(
1769 1847 'wpsc-ap-dashboard',
1770 1848 array(
1771 - 'card-body-bg-color' => '#f9f9f9',
1849 + 'card-body-bg-color' => '#ffffff',
1772 1850 'card-body-svg-color' => '#777',
1773 1851 'card-body-text-color' => '#2c3e50',
1774 - 'widget-body-bg-color' => '#f9f9f9',
1852 + 'widget-body-bg-color' => '#ffffff',
1775 1853 'widget-body-svg-color' => '#777',
1776 1854 'widget-body-text-color' => '#2c3e50',
1777 1855 )
1778 1856 );
@@ -1959,8 +2037,83 @@
1959 2037 self::create_indexing();
1960 2038
1961 2039 // update string translations.
1962 2040 update_option( 'wpsc-string-translation', $string_translations );
2041 +
2042 + // Add AI assistant option.
2043 + update_option(
2044 + 'wpsc-ps-ai-assistant-settings',
2045 + array(
2046 + 'status' => '0',
2047 + 'provider' => 'openai',
2048 + 'api_key' => '',
2049 + 'model' => 'gpt-4o-mini',
2050 + 'max-tokens' => 500,
2051 + 'auto-delete-ai-logs-time' => 1,
2052 + 'auto-delete-ai-logs-unit' => 'year',
2053 + 'custom-prompt' => '',
2054 + 'summary-custom-prompt' => '',
2055 + 'auto-draft-custom-prompt' => '',
2056 + 'is-active' => 0,
2057 + 'last-error' => '',
2058 + 'ai-max-upload-file-size' => 10,
2059 + )
2060 + );
2061 +
2062 + // update AI training options.
2063 + update_option(
2064 + 'wpsc-ps-ai-training-sources',
2065 + array(
2066 + array(
2067 + 'slug' => 'local',
2068 + 'type' => 'localhost',
2069 + 'name' => 'Local',
2070 + 'api-url' => rest_url(),
2071 + 'post-types' => array(),
2072 + ),
2073 + ),
2074 + );
2075 +
2076 + // default AI chatbot settings.
2077 + update_option(
2078 + 'wpsc-ps-acb-chatbot-settings',
2079 + array(
2080 + 'status' => '0',
2081 + 'delete-acb-session-time' => 1,
2082 + 'delete-acb-session-unit' => 'year',
2083 + 'show-footer-branding' => '1',
2084 + 'sessions-per-page' => 30,
2085 + 'popup-delay-status' => '0',
2086 + 'popup-delay' => 10,
2087 + 'popup-display-limit' => 3,
2088 + 'custom-prompt' => '',
2089 + )
2090 + );
2091 +
2092 + // default chatbot appearance settings.
2093 + update_option(
2094 + 'wpsc-acb-appearance-general',
2095 + array(
2096 + 'background-color' => '#2271b1',
2097 + 'icon-color' => '#ffffff',
2098 + 'header-text' => __( 'AI Chatbot', 'supportcandy' ),
2099 + 'greeting-text' => __( 'Hey, I\'m your assistant. How can I help you today?', 'supportcandy' ),
2100 + 'warning-text' => __( 'AI can make mistakes. Check important info.', 'supportcandy' ),
2101 + )
2102 + );
2103 +
2104 + // Onboarding wizard: seed pending state for this fresh install and flag a
2105 + // one-time redirect so WPSC_Onboarding shows the wizard on the next admin
2106 + // page load. Existing sites being upgraded never reach this method, so the
2107 + // wizard never auto-appears for them.
2108 + update_option(
2109 + 'wpsc-onboarding-wizard',
2110 + array(
2111 + 'status' => 'pending',
2112 + 'steps' => array(),
2113 + )
2114 + );
2115 + set_transient( 'wpsc_onboarding_redirect', 1, 5 * MINUTE_IN_SECONDS );
1963 2116 }
1964 2117
1965 2118 /**
1966 2119 * Upgrade the version
@@ -2425,12 +2578,12 @@
2425 2578 // dashboard appreance general setting.
2426 2579 update_option(
2427 2580 'wpsc-ap-dashboard',
2428 2581 array(
2429 - 'card-body-bg-color' => '#f9f9f9',
2582 + 'card-body-bg-color' => '#ffffff',
2430 2583 'card-body-svg-color' => '#777',
2431 2584 'card-body-text-color' => '#2c3e50',
2432 - 'widget-body-bg-color' => '#f9f9f9',
2585 + 'widget-body-bg-color' => '#ffffff',
2433 2586 'widget-body-svg-color' => '#777',
2434 2587 'widget-body-text-color' => '#2c3e50',
2435 2588 )
2436 2589 );
@@ -2709,8 +2862,206 @@
2709 2862 unset( $recaptcha['allow-recaptcha'] );
2710 2863 update_option( 'wpsc-recaptcha-settings', $recaptcha );
2711 2864 }
2712 2865
2866 + if ( version_compare( self::$current_version, '3.5.1', '<' ) ) {
2867 +
2868 + // AI assistant feature moved into core - seed defaults for sites upgrading from an older core version.
2869 + if ( false === get_option( 'wpsc-ps-ai-assistant-settings', false ) ) {
2870 + update_option(
2871 + 'wpsc-ps-ai-assistant-settings',
2872 + array(
2873 + 'status' => '0',
2874 + 'provider' => 'openai',
2875 + 'api_key' => '',
2876 + 'model' => 'gpt-4o-mini',
2877 + 'max-tokens' => 500,
2878 + 'auto-delete-ai-logs-time' => 1,
2879 + 'auto-delete-ai-logs-unit' => 'year',
2880 + 'custom-prompt' => '',
2881 + 'summary-custom-prompt' => '',
2882 + 'auto-draft-custom-prompt' => '',
2883 + 'is-active' => 0,
2884 + 'last-error' => '',
2885 + 'ai-max-upload-file-size' => 10,
2886 + )
2887 + );
2888 + }
2889 +
2890 + if ( false === get_option( 'wpsc-ps-ai-training-sources', false ) ) {
2891 + update_option(
2892 + 'wpsc-ps-ai-training-sources',
2893 + array(
2894 + array(
2895 + 'slug' => 'local',
2896 + 'type' => 'localhost',
2897 + 'name' => 'Local',
2898 + 'api-url' => rest_url(),
2899 + 'post-types' => array(),
2900 + ),
2901 + ),
2902 + );
2903 + }
2904 +
2905 + // AI chatbot feature moved into core - seed defaults for sites upgrading from an older core version.
2906 + if ( false === get_option( 'wpsc-ps-acb-chatbot-settings', false ) ) {
2907 + update_option(
2908 + 'wpsc-ps-acb-chatbot-settings',
2909 + array(
2910 + 'status' => '0',
2911 + 'delete-acb-session-time' => 1,
2912 + 'delete-acb-session-unit' => 'year',
2913 + 'show-footer-branding' => '1',
2914 + 'sessions-per-page' => 30,
2915 + 'popup-delay-status' => '0',
2916 + 'popup-delay' => 10,
2917 + 'popup-display-limit' => 3,
2918 + 'custom-prompt' => '',
2919 + )
2920 + );
2921 + }
2922 +
2923 + if ( false === get_option( 'wpsc-acb-appearance-general', false ) ) {
2924 + update_option(
2925 + 'wpsc-acb-appearance-general',
2926 + array(
2927 + 'background-color' => '#2271b1',
2928 + 'icon-color' => '#ffffff',
2929 + 'header-text' => __( 'AI Chatbot', 'supportcandy' ),
2930 + 'greeting-text' => __( 'Hey, I\'m your assistant. How can I help you today?', 'supportcandy' ),
2931 + 'warning-text' => __( 'AI can make mistakes. Check important info.', 'supportcandy' ),
2932 + )
2933 + );
2934 + }
2935 +
2936 + // Migrate legacy AI training data - only for sites that already used AI assistant / AI chatbot via Productivity Suite.
2937 + $ps_settings = get_option( 'wpsc-ps-settings', array() );
2938 +
2939 + $wpdb->query( "UPDATE {$wpdb->prefix}psmsc_ai_training SET doc_source = 'local' WHERE source NOT IN ( 'file', 'url', 'ticket' )" );
2940 + $wpdb->query( "UPDATE {$wpdb->prefix}psmsc_ai_training SET doc_source = '' WHERE source IN ( 'file', 'url', 'ticket' )" );
2941 +
2942 + // update AI training options.
2943 + $local_post_types = array(
2944 + array(
2945 + 'slug' => 'post',
2946 + 'name' => 'Posts',
2947 + 'status' => 0,
2948 + 'endpoint' => rest_url( 'wp/v2/posts' ),
2949 + ),
2950 + array(
2951 + 'slug' => 'page',
2952 + 'name' => 'Pages',
2953 + 'status' => 0,
2954 + 'endpoint' => rest_url( 'wp/v2/pages' ),
2955 + ),
2956 + );
2957 +
2958 + $bd_settings = get_option( 'wpsc-ps-ai-bd-settings', array() );
2959 + if ( isset( $bd_settings['bd-status'] ) && $bd_settings['bd-status'] == 1 ) {
2960 + $local_post_types[] = array(
2961 + 'slug' => 'docs',
2962 + 'name' => 'Betterdocs',
2963 + 'status' => 1,
2964 + 'endpoint' => rest_url( 'wp/v2/docs' ),
2965 + );
2966 +
2967 + // Update source column for betterdocs source.
2968 + $wpdb->query( "UPDATE {$wpdb->prefix}psmsc_ai_training SET source = 'docs' WHERE source = 'betterdocs'" );
2969 + }
2970 +
2971 + update_option(
2972 + 'wpsc-ps-ai-training-sources',
2973 + array(
2974 + array(
2975 + 'slug' => 'local',
2976 + 'type' => 'localhost',
2977 + 'name' => 'Local',
2978 + 'api-url' => rest_url(),
2979 + 'post-types' => $local_post_types,
2980 + ),
2981 + ),
2982 + );
2983 +
2984 + // wpsc_ps_ai_categories is no longer used - post-type training sources are
2985 + // now routed directly by source type instead of through a categories registry.
2986 + delete_option( 'wpsc_ps_ai_categories' );
2987 +
2988 + // remove 'category', 'is_expire' and 'expiry_date' columns from AI training table.
2989 + foreach ( array( 'category', 'is_expire', 'expiry_date' ) as $column ) {
2990 + $column_exists = $wpdb->get_results( "SHOW COLUMNS FROM {$wpdb->prefix}psmsc_ai_training LIKE '{$column}'" );
2991 + if ( ! empty( $column_exists ) ) {
2992 + $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_ai_training DROP COLUMN {$column}" );
2993 + }
2994 + }
2995 +
2996 + // unschedule expired training cleanup cron, this feature has been removed.
2997 + wp_clear_scheduled_hook( 'wpsc_auto_delete_ai_training_expired_records' );
2998 +
2999 + // remove 'manage-ai-training' capability, this is no longer used.
3000 + $roles = get_option( 'wpsc-agent-roles', array() );
3001 + foreach ( $roles as $key => $role ) {
3002 + unset( $role['caps']['manage-ai-training'] );
3003 + $roles[ $key ] = $role;
3004 + }
3005 + update_option( 'wpsc-agent-roles', $roles );
3006 +
3007 + if ( isset( $ai_assistant['is-active'] ) ) {
3008 + $ai_assistant = get_option( 'wpsc-ps-ai-assistant-settings' );
3009 + $ai_assistant['status'] = $ai_assistant['is-active'] ? 1 : 0;
3010 + update_option( 'wpsc-ps-ai-assistant-settings', $ai_assistant );
3011 + }
3012 +
3013 + // enable chatbot feature.
3014 + if ( isset( $ps_settings['ai-chatbot'] ) ) {
3015 + $chatbot = get_option( 'wpsc-ps-acb-chatbot-settings' );
3016 + $chatbot['status'] = $ps_settings['ai-chatbot'] ? 1 : 0;
3017 + update_option( 'wpsc-ps-acb-chatbot-settings', $chatbot );
3018 + }
3019 + }
3020 +
3021 + if ( version_compare( self::$current_version, '3.5.2', '<' ) ) {
3022 +
3023 + $chatbot = get_option( 'wpsc-ps-acb-chatbot-settings' );
3024 + $chatbot['popup-delay-status'] = '0';
3025 + $chatbot['popup-delay'] = 10;
3026 + $chatbot['popup-display-limit'] = 3;
3027 + update_option( 'wpsc-ps-acb-chatbot-settings', $chatbot );
3028 + }
3029 +
3030 + if ( version_compare( self::$current_version, '3.5.3', '<' ) ) {
3031 +
3032 + $chatbot = get_option( 'wpsc-ps-acb-chatbot-settings' );
3033 + $chatbot['custom-prompt'] = '';
3034 + update_option( 'wpsc-ps-acb-chatbot-settings', $chatbot );
3035 + }
3036 +
3037 + if ( version_compare( self::$current_version, '3.5.4', '<' ) ) {
3038 +
3039 + $appearance = get_option( 'wpsc-acb-appearance-general' );
3040 + if ( is_array( $appearance ) ) {
3041 + if ( ! isset( $appearance['header-text'] ) ) {
3042 + $appearance['header-text'] = __( 'AI Chatbot', 'supportcandy' );
3043 + }
3044 + if ( ! isset( $appearance['greeting-text'] ) ) {
3045 + $appearance['greeting-text'] = __( 'Hey, I\'m your assistant. How can I help you today?', 'supportcandy' );
3046 + }
3047 + if ( ! isset( $appearance['warning-text'] ) ) {
3048 + $appearance['warning-text'] = __( 'AI can make mistakes. Check important info.', 'supportcandy' );
3049 + }
3050 + update_option( 'wpsc-acb-appearance-general', $appearance );
3051 + }
3052 +
3053 + self::create_indexing();
3054 +
3055 + update_option(
3056 + 'wpsc-onboarding-wizard',
3057 + array(
3058 + 'status' => 'completed',
3059 + 'steps' => array(),
3060 + )
3061 + );
3062 + }
3063 +
2713 3064 update_option( 'wpsc-string-translation', $string_translations );
2714 3065 self::set_upgrade_complete();
2715 3066 }
2716 3067
@@ -2815,8 +3166,20 @@
2815 3166 )
2816 3167 );
2817 3168 if ( ! $index_exists ) {
2818 3169 $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_archived_threads ADD INDEX {$index_name} (ticket)" );
3170 + }
3171 +
3172 + // Create index on AI training table.
3173 + $index_name = 'idx_doc_source_source_provider_source_id';
3174 + $index_exists = $wpdb->get_var(
3175 + $wpdb->prepare(
3176 + "SHOW INDEX FROM {$wpdb->prefix}psmsc_ai_training WHERE Key_name = %s",
3177 + $index_name
3178 + )
3179 + );
3180 + if ( ! $index_exists ) {
3181 + $wpdb->query( "ALTER TABLE {$wpdb->prefix}psmsc_ai_training ADD INDEX {$index_name} (doc_source, source, provider, source_id)" );
2819 3182 }
2820 3183 }
2821 3184 }
2822 3185 endif;