| @@ -834,28 +834,12 @@ | ||
| 834 | 834 | $meta = Meta::where([ |
| 835 | 835 | 'object_type' => 'fluent_bot_settings', |
| 836 | 836 | 'object_id' => 1, |
| 837 | 837 | 'key' => '_fs_fluent_bot_config' |
| 838 | - ])->orderByDesc('id')->first(); | |
| 838 | + ])->first(); | |
| 839 | 839 | |
| 840 | 840 | $settings = $meta ? Helper::safeUnserialize($meta->value) : []; |
| 841 | 841 | |
| 842 | - if (!is_array($settings)) { | |
| 843 | - $settings = []; | |
| 844 | - } | |
| 845 | - | |
| 846 | - unset($settings['generalApiKey']); | |
| 847 | - | |
| 848 | - if (!empty($settings['productMappings']) && is_array($settings['productMappings'])) { | |
| 849 | - $settings['productMappings'] = array_map(function ($mapping) { | |
| 850 | - if (!is_array($mapping)) { | |
| 851 | - return $mapping; | |
| 852 | - } | |
| 853 | - unset($mapping['apiKey']); | |
| 854 | - return $mapping; | |
| 855 | - }, $settings['productMappings']); | |
| 856 | - } | |
| 857 | - | |
| 858 | 842 | $productItems = Product::all()->map(function ($product) { |
| 859 | 843 | return [ |
| 860 | 844 | 'id' => $product->id, |
| 861 | 845 | 'title' => $product->title |
| @@ -861,19 +845,15 @@ | ||
| 861 | 845 | 'title' => $product->title |
| 862 | 846 | ]; |
| 863 | 847 | })->values()->all(); |
| 864 | 848 | |
| 865 | - // Default generalBotEnabled to true for backward compatibility with configs saved | |
| 866 | - // before this flag existed — existing installs expect general bot to work on GET. | |
| 867 | - $defaults = [ | |
| 868 | - 'generalBotId' => '', | |
| 869 | - 'generalBotEnabled' => true, | |
| 870 | - 'isEnabled' => false, | |
| 871 | - 'productMappings' => [], | |
| 872 | - 'products' => $productItems, | |
| 873 | - ]; | |
| 874 | - | |
| 875 | - return array_merge($defaults, $settings, [ | |
| 849 | + return array_merge([ | |
| 850 | + 'generalApiKey' => '', | |
| 851 | + 'generalBotId' => '', | |
| 852 | + 'isEnabled' => false, | |
| 853 | + 'productMappings' => [], | |
| 854 | + 'products' => $productItems | |
| 855 | + ], $settings, [ | |
| 876 | 856 | 'products' => $productItems |
| 877 | 857 | ]); |
| 878 | 858 | } |
| 879 | 859 | |
| @@ -879,16 +859,14 @@ | ||
| 879 | 859 | |
| 880 | 860 | public function saveFluentBotSettings(Request $request) |
| 881 | 861 | { |
| 882 | 862 | $data = [ |
| 883 | - 'generalBotId' => $request->getSafe('generalBotId', 'sanitize_text_field'), | |
| 884 | - 'generalBotEnabled' => filter_var($request->get('generalBotEnabled', true), FILTER_VALIDATE_BOOLEAN), | |
| 885 | - 'isEnabled' => $request->getSafe('isEnabled', 'rest_sanitize_boolean'), | |
| 863 | + 'generalBotId' => $request->getSafe('generalBotId', 'sanitize_text_field'), | |
| 864 | + 'isEnabled' => $request->getSafe('isEnabled', 'rest_sanitize_boolean'), | |
| 886 | 865 | 'productMappings' => [] |
| 887 | 866 | ]; |
| 888 | 867 | |
| 889 | 868 | $productMappings = (array) $request->get('productMappings', []); |
| 890 | - $seenProductIds = []; | |
| 891 | 869 | |
| 892 | 870 | foreach ($productMappings as $mapping) { |
| 893 | 871 | if (!is_array($mapping)) { |
| 894 | 872 | continue; |
| @@ -893,47 +871,33 @@ | ||
| 893 | 871 | if (!is_array($mapping)) { |
| 894 | 872 | continue; |
| 895 | 873 | } |
| 896 | 874 | |
| 897 | - $productId = intval($mapping['productId'] ?? 0); | |
| 898 | - $botId = trim(sanitize_text_field($mapping['botId'] ?? '')); | |
| 899 | - | |
| 900 | - // Drop invalid rows: empty botId would override the general bot with nothing | |
| 901 | - // at resolution time (resolveApiCredentials), producing runtime failures. | |
| 902 | - if ($productId < 1 || $botId === '') { | |
| 903 | - continue; | |
| 904 | - } | |
| 905 | - | |
| 906 | - // Dedupe by productId — first valid mapping wins. | |
| 907 | - if (isset($seenProductIds[$productId])) { | |
| 908 | - continue; | |
| 909 | - } | |
| 910 | - $seenProductIds[$productId] = true; | |
| 911 | - | |
| 912 | 875 | $data['productMappings'][] = [ |
| 913 | - 'productId' => $productId, | |
| 876 | + 'productId' => intval($mapping['productId'] ?? 0), | |
| 914 | 877 | 'productTitle' => sanitize_text_field($mapping['productTitle'] ?? ''), |
| 915 | - 'botId' => $botId, | |
| 878 | + 'botId' => sanitize_text_field($mapping['botId'] ?? ''), | |
| 916 | 879 | ]; |
| 917 | 880 | } |
| 918 | 881 | |
| 919 | 882 | $serialized = maybe_serialize($data); |
| 920 | 883 | |
| 921 | - $where = [ | |
| 884 | + $existing = Meta::where([ | |
| 922 | 885 | 'object_type' => 'fluent_bot_settings', |
| 923 | 886 | 'object_id' => 1, |
| 924 | 887 | 'key' => '_fs_fluent_bot_config' |
| 925 | - ]; | |
| 888 | + ])->first(); | |
| 926 | 889 | |
| 927 | - $existing = Meta::where($where)->orderByDesc('id')->first(); | |
| 928 | - | |
| 929 | 890 | if ($existing) { |
| 930 | - // Update the latest row; do not prune siblings — concurrent first-writes could | |
| 931 | - // race and delete each other's inserts, leaving zero rows (data loss). | |
| 932 | - // Reads use orderByDesc('id')->first() so duplicates are harmless at read time. | |
| 933 | 891 | $existing->update(['value' => $serialized]); |
| 934 | 892 | } else { |
| 935 | - Meta::create(array_merge($where, ['value' => $serialized])); | |
| 893 | + Meta::create([ | |
| 894 | + 'object_type' => 'fluent_bot_settings', | |
| 895 | + 'object_id' => 1, | |
| 896 | + 'key' => '_fs_fluent_bot_config', | |
| 897 | + 'value' => $serialized | |
| 898 | + ]); | |
| 899 | + | |
| 936 | 900 | AIActivityLogsMigrator::migrate(); |
| 937 | 901 | } |
| 938 | 902 | |
| 939 | 903 | return [ |
| @@ -939,36 +903,8 @@ | ||
| 939 | 903 | return [ |
| 940 | 904 | 'success' => true, |
| 941 | 905 | 'message' => 'Settings saved successfully', |
| 942 | 906 | 'data' => $data |
| 943 | - ]; | |
| 944 | - } | |
| 945 | - | |
| 946 | - public function getFluentBotPresets() | |
| 947 | - { | |
| 948 | - $service = new \FluentSupport\App\Services\Integrations\FluentBot\FluentBotService(); | |
| 949 | - $custom = $service->getCustomPresets(); | |
| 950 | - | |
| 951 | - if (!empty($custom)) { | |
| 952 | - return ['presets' => $custom]; | |
| 953 | - } | |
| 954 | - | |
| 955 | - // Return defaults without persisting — saving happens only when the user explicitly posts. | |
| 956 | - $helper = new \FluentSupport\App\Services\Integrations\FluentBot\FluentBotHelper(); | |
| 957 | - return ['presets' => $helper->getPresetPrompts('createResponse')]; | |
| 958 | - } | |
| 959 | - | |
| 960 | - public function saveFluentBotPresets(Request $request) | |
| 961 | - { | |
| 962 | - $presets = (array) $request->get('presets', []); | |
| 963 | - | |
| 964 | - $service = new \FluentSupport\App\Services\Integrations\FluentBot\FluentBotService(); | |
| 965 | - $saved = $service->saveCustomPresets($presets); | |
| 966 | - | |
| 967 | - return [ | |
| 968 | - 'success' => true, | |
| 969 | - 'message' => __('Prompt options saved successfully', 'fluent-support'), | |
| 970 | - 'presets' => $saved | |
| 971 | 907 | ]; |
| 972 | 908 | } |
| 973 | 909 | |
| 974 | 910 | } |