| @@ -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( |
| @@ -1479,12 +1564,14 @@ | ||
| 1479 | 1564 | |
| 1480 | 1565 | update_option( |
| 1481 | 1566 | 'wpsc-recaptcha-settings', |
| 1482 | 1567 | array( |
| 1483 | - 'allow-recaptcha' => 0, | |
| 1484 | - 'recaptcha-version' => 3, | |
| 1485 | - 'recaptcha-site-key' => '', | |
| 1486 | - 'recaptcha-secret-key' => '', | |
| 1568 | + 'captcha-provider' => 0, | |
| 1569 | + 'recaptcha-version' => 3, | |
| 1570 | + 'recaptcha-site-key' => '', | |
| 1571 | + 'recaptcha-secret-key' => '', | |
| 1572 | + 'cloudflare-site-key' => '', | |
| 1573 | + 'cloudflare-secret-key' => '', | |
| 1487 | 1574 | ) |
| 1488 | 1575 | ); |
| 1489 | 1576 | |
| 1490 | 1577 | update_option( |
| @@ -1506,8 +1593,10 @@ | ||
| 1506 | 1593 | 'auto-archive-tickets-time' => 0, |
| 1507 | 1594 | 'auto-archive-tickets-unit' => 'days', |
| 1508 | 1595 | 'permanent-archive-tickets-time' => 0, |
| 1509 | 1596 | 'permanent-archive-tickets-unit' => 'days', |
| 1597 | + 'permanent-delete-tickets-time' => 0, | |
| 1598 | + 'permanent-delete-tickets-unit' => 'days', | |
| 1510 | 1599 | 'allow-bcc' => 0, |
| 1511 | 1600 | 'allow-cc' => 0, |
| 1512 | 1601 | 'view-more' => 1, |
| 1513 | 1602 | 'allow-reply-to-close-ticket' => array( 'customer', 'agent' ), |
| @@ -1730,15 +1819,8 @@ | ||
| 1730 | 1819 | 'z-index' => 900000000, |
| 1731 | 1820 | ) |
| 1732 | 1821 | ); |
| 1733 | 1822 | update_option( |
| 1734 | - 'wpsc-ap-agent-collision', | |
| 1735 | - array( | |
| 1736 | - 'header-bg-color' => '#e6e6e6', | |
| 1737 | - 'header-text-color' => '#2c3e50', | |
| 1738 | - ) | |
| 1739 | - ); | |
| 1740 | - update_option( | |
| 1741 | 1823 | 'wpsc-ap-ticket-list', |
| 1742 | 1824 | array( |
| 1743 | 1825 | 'list-header-background-color' => '#2c3e50', |
| 1744 | 1826 | 'list-header-text-color' => '#fff', |
| @@ -1763,12 +1845,12 @@ | ||
| 1763 | 1845 | // dashboard general setting. |
| 1764 | 1846 | update_option( |
| 1765 | 1847 | 'wpsc-ap-dashboard', |
| 1766 | 1848 | array( |
| 1767 | - 'card-body-bg-color' => '#f9f9f9', | |
| 1849 | + 'card-body-bg-color' => '#ffffff', | |
| 1768 | 1850 | 'card-body-svg-color' => '#777', |
| 1769 | 1851 | 'card-body-text-color' => '#2c3e50', |
| 1770 | - 'widget-body-bg-color' => '#f9f9f9', | |
| 1852 | + 'widget-body-bg-color' => '#ffffff', | |
| 1771 | 1853 | 'widget-body-svg-color' => '#777', |
| 1772 | 1854 | 'widget-body-text-color' => '#2c3e50', |
| 1773 | 1855 | ) |
| 1774 | 1856 | ); |
| @@ -1955,8 +2037,83 @@ | ||
| 1955 | 2037 | self::create_indexing(); |
| 1956 | 2038 | |
| 1957 | 2039 | // update string translations. |
| 1958 | 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 ); | |
| 1959 | 2116 | } |
| 1960 | 2117 | |
| 1961 | 2118 | /** |
| 1962 | 2119 | * Upgrade the version |
| @@ -2421,12 +2578,12 @@ | ||
| 2421 | 2578 | // dashboard appreance general setting. |
| 2422 | 2579 | update_option( |
| 2423 | 2580 | 'wpsc-ap-dashboard', |
| 2424 | 2581 | array( |
| 2425 | - 'card-body-bg-color' => '#f9f9f9', | |
| 2582 | + 'card-body-bg-color' => '#ffffff', | |
| 2426 | 2583 | 'card-body-svg-color' => '#777', |
| 2427 | 2584 | 'card-body-text-color' => '#2c3e50', |
| 2428 | - 'widget-body-bg-color' => '#f9f9f9', | |
| 2585 | + 'widget-body-bg-color' => '#ffffff', | |
| 2429 | 2586 | 'widget-body-svg-color' => '#777', |
| 2430 | 2587 | 'widget-body-text-color' => '#2c3e50', |
| 2431 | 2588 | ) |
| 2432 | 2589 | ); |
| @@ -2695,8 +2852,216 @@ | ||
| 2695 | 2852 | update_option( 'wpsc-string-translation', $string_translations ); |
| 2696 | 2853 | } |
| 2697 | 2854 | } |
| 2698 | 2855 | |
| 2856 | + if ( version_compare( self::$current_version, '3.4.8', '<' ) ) { | |
| 2857 | + | |
| 2858 | + $recaptcha = get_option( 'wpsc-recaptcha-settings' ); | |
| 2859 | + $recaptcha['captcha-provider'] = $recaptcha['allow-recaptcha'] ? 'google-recaptcha' : '0'; | |
| 2860 | + $recaptcha['cloudflare-site-key'] = ''; | |
| 2861 | + $recaptcha['cloudflare-secret-key'] = ''; | |
| 2862 | + unset( $recaptcha['allow-recaptcha'] ); | |
| 2863 | + update_option( 'wpsc-recaptcha-settings', $recaptcha ); | |
| 2864 | + } | |
| 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 | + | |
| 2699 | 3064 | update_option( 'wpsc-string-translation', $string_translations ); |
| 2700 | 3065 | self::set_upgrade_complete(); |
| 2701 | 3066 | } |
| 2702 | 3067 | |
| @@ -2801,8 +3166,20 @@ | ||
| 2801 | 3166 | ) |
| 2802 | 3167 | ); |
| 2803 | 3168 | if ( ! $index_exists ) { |
| 2804 | 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)" ); | |
| 2805 | 3182 | } |
| 2806 | 3183 | } |
| 2807 | 3184 | } |
| 2808 | 3185 | endif; |