| @@ -59,8 +59,11 @@ | ||
| 59 | 59 | add_action('wp_ajax_mxchat_paginate_entries', array($this, 'ajax_mxchat_paginate_entries')); |
| 60 | 60 | add_action('wp_ajax_mxchat_get_entry_content', array($this, 'ajax_mxchat_get_entry_content')); |
| 61 | 61 | add_action('wp_ajax_mxchat_save_entry_content', array($this, 'ajax_mxchat_save_entry_content')); |
| 62 | 62 | |
| 63 | + // Hook for content deletion | |
| 64 | + add_action('mxchat_delete_content', array($this, 'mxchat_delete_from_pinecone_by_url'), 10, 1); | |
| 65 | + | |
| 63 | 66 | // WordPress post management hooks |
| 64 | 67 | add_action('pre_post_update', array($this, 'mxchat_store_pre_update_status'), 10, 2); |
| 65 | 68 | add_action('post_updated', array($this, 'mxchat_handle_post_update'), 10, 3); |
| 66 | 69 | add_action('before_delete_post', array($this, 'mxchat_handle_post_delete')); |
| @@ -990,18 +993,10 @@ | ||
| 990 | 993 | wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts'))); |
| 991 | 994 | exit; |
| 992 | 995 | } |
| 993 | 996 | |
| 994 | - // Fetch URL — use browser-like headers so servers with bot protection don't block us | |
| 995 | - $response = wp_remote_get($submitted_url, array( | |
| 996 | - 'timeout' => 30, | |
| 997 | - 'sslverify' => false, | |
| 998 | - 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', | |
| 999 | - 'headers' => array( | |
| 1000 | - 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', | |
| 1001 | - 'Accept-Language' => 'en-US,en;q=0.9', | |
| 1002 | - ), | |
| 1003 | - )); | |
| 997 | + // Fetch URL | |
| 998 | + $response = wp_remote_get($submitted_url, array('timeout' => 30)); | |
| 1004 | 999 | |
| 1005 | 1000 | if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) { |
| 1006 | 1001 | $error_message = is_wp_error($response) ? $response->get_error_message() : 'HTTP Status: ' . wp_remote_retrieve_response_code($response); |
| 1007 | 1002 | set_transient('mxchat_admin_notice_error', |
| @@ -2835,12 +2830,11 @@ | ||
| 2835 | 2830 | foreach ($primary_indexes as $path => $source) { |
| 2836 | 2831 | $url = trailingslashit($site_url) . $path; |
| 2837 | 2832 | |
| 2838 | 2833 | $response = wp_remote_head($url, array( |
| 2839 | - 'timeout' => 10, | |
| 2834 | + 'timeout' => 3, // Short timeout | |
| 2840 | 2835 | 'sslverify' => false, |
| 2841 | - 'redirection' => 1, | |
| 2842 | - 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', | |
| 2836 | + 'redirection' => 1 | |
| 2843 | 2837 | )); |
| 2844 | 2838 | |
| 2845 | 2839 | if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) { |
| 2846 | 2840 | // Found a sitemap index - parse it to get sub-sitemaps |
| @@ -2898,15 +2892,10 @@ | ||
| 2898 | 2892 | private function parse_sitemap_index($url) { |
| 2899 | 2893 | $sub_sitemaps = array(); |
| 2900 | 2894 | |
| 2901 | 2895 | $response = wp_remote_get($url, array( |
| 2902 | - 'timeout' => 30, | |
| 2903 | - 'sslverify' => false, | |
| 2904 | - 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', | |
| 2905 | - 'headers' => array( | |
| 2906 | - 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', | |
| 2907 | - 'Accept-Language' => 'en-US,en;q=0.9', | |
| 2908 | - ), | |
| 2896 | + 'timeout' => 5, | |
| 2897 | + 'sslverify' => false | |
| 2909 | 2898 | )); |
| 2910 | 2899 | |
| 2911 | 2900 | if (is_wp_error($response)) { |
| 2912 | 2901 | return $sub_sitemaps; |
| @@ -2957,15 +2946,10 @@ | ||
| 2957 | 2946 | * Get URL count from a sitemap |
| 2958 | 2947 | */ |
| 2959 | 2948 | private function get_sitemap_url_count($url) { |
| 2960 | 2949 | $response = wp_remote_get($url, array( |
| 2961 | - 'timeout' => 30, | |
| 2962 | - 'sslverify' => false, | |
| 2963 | - 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', | |
| 2964 | - 'headers' => array( | |
| 2965 | - 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', | |
| 2966 | - 'Accept-Language' => 'en-US,en;q=0.9', | |
| 2967 | - ), | |
| 2950 | + 'timeout' => 10, | |
| 2951 | + 'sslverify' => false | |
| 2968 | 2952 | )); |
| 2969 | 2953 | |
| 2970 | 2954 | if (is_wp_error($response)) { |
| 2971 | 2955 | return 0; |
| @@ -2988,11 +2972,10 @@ | ||
| 2988 | 2972 | $sitemaps = array(); |
| 2989 | 2973 | $robots_url = trailingslashit($site_url) . 'robots.txt'; |
| 2990 | 2974 | |
| 2991 | 2975 | $response = wp_remote_get($robots_url, array( |
| 2992 | - 'timeout' => 15, | |
| 2993 | - 'sslverify' => false, | |
| 2994 | - 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', | |
| 2976 | + 'timeout' => 5, | |
| 2977 | + 'sslverify' => false | |
| 2995 | 2978 | )); |
| 2996 | 2979 | |
| 2997 | 2980 | if (is_wp_error($response)) { |
| 2998 | 2981 | return $sitemaps; |
| @@ -5181,33 +5164,40 @@ | ||
| 5181 | 5164 | // If the post was previously published but is now not published, remove from knowledge base |
| 5182 | 5165 | if ($previous_status === 'publish' && $post->post_status !== 'publish') { |
| 5183 | 5166 | // Use the stored URL from when it was published, or fall back to current permalink |
| 5184 | 5167 | $source_url = $previous_url ?: get_permalink($post_id); |
| 5168 | + | |
| 5169 | + if ($source_url) { | |
| 5170 | + // Check if Pinecone is enabled | |
| 5171 | + $pinecone_options = get_option('mxchat_pinecone_addon_options', array()); | |
| 5172 | + $use_pinecone = ($pinecone_options['mxchat_use_pinecone'] ?? '0') === '1'; | |
| 5185 | 5173 | |
| 5186 | - if ($source_url) { | |
| 5187 | - // Chunk-aware deletion (routes to Pinecone or WP DB and removes base + all chunks) | |
| 5188 | - MxChat_Utils::delete_chunks_for_url($source_url, 'default'); | |
| 5174 | + if ($use_pinecone && !empty($pinecone_options['mxchat_pinecone_api_key'])) { | |
| 5175 | + // Delete from Pinecone | |
| 5176 | + $this->mxchat_delete_from_pinecone_by_url($source_url, $pinecone_options); | |
| 5177 | + } else { | |
| 5178 | + // Delete from WordPress DB | |
| 5179 | + global $wpdb; | |
| 5180 | + $table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; | |
| 5181 | + | |
| 5182 | + $result = $wpdb->delete( | |
| 5183 | + $table_name, | |
| 5184 | + array('source_url' => $source_url), | |
| 5185 | + array('%s') | |
| 5186 | + ); | |
| 5187 | + } | |
| 5189 | 5188 | } |
| 5190 | - | |
| 5189 | + | |
| 5191 | 5190 | // Clean up the transients and exit early |
| 5192 | 5191 | delete_transient($previous_status_key); |
| 5193 | 5192 | delete_transient($previous_url_key); |
| 5194 | 5193 | return; |
| 5195 | 5194 | } |
| 5196 | - | |
| 5197 | - // Slug/permalink rename while still published: delete the old vectors before upserting new ones. | |
| 5198 | - // Without this, md5(old_url) vectors (base + chunks) would be orphaned under the stale URL. | |
| 5199 | - if ($post->post_status === 'publish' && !empty($previous_url)) { | |
| 5200 | - $current_url = get_permalink($post_id); | |
| 5201 | - if ($current_url && $current_url !== $previous_url) { | |
| 5202 | - MxChat_Utils::delete_chunks_for_url($previous_url, 'default'); | |
| 5203 | - } | |
| 5204 | - } | |
| 5205 | - | |
| 5195 | + | |
| 5206 | 5196 | // Store the current status for next time (if this is an update) |
| 5207 | 5197 | if ($update) { |
| 5208 | 5198 | set_transient($previous_status_key, $post->post_status, DAY_IN_SECONDS); |
| 5209 | - | |
| 5199 | + | |
| 5210 | 5200 | // If the post is currently published, also store its URL |
| 5211 | 5201 | if ($post->post_status === 'publish') { |
| 5212 | 5202 | $current_url = get_permalink($post_id); |
| 5213 | 5203 | set_transient($previous_url_key, $current_url, DAY_IN_SECONDS); |
| @@ -5437,14 +5427,12 @@ | ||
| 5437 | 5427 | if (!$should_sync) { |
| 5438 | 5428 | return; |
| 5439 | 5429 | } |
| 5440 | 5430 | |
| 5441 | - // Resolve the pre-trash URL. wp_trash_post renames the slug with "__trashed" before firing | |
| 5442 | - // this hook, so get_permalink() here would return the trashed URL and md5() would miss the | |
| 5443 | - // real vector IDs stored under the original URL. | |
| 5444 | - $source_url = $this->mxchat_resolve_pre_trash_url($post_id); | |
| 5431 | + // Get the URL before post is deleted | |
| 5432 | + $source_url = get_permalink($post_id); | |
| 5445 | 5433 | if (!$source_url) { |
| 5446 | - //error_log('MXChat: Failed to resolve source URL for post ' . $post_id); | |
| 5434 | + //error_log('MXChat: Failed to get permalink for post ' . $post_id); | |
| 5447 | 5435 | return; |
| 5448 | 5436 | } |
| 5449 | 5437 | |
| 5450 | 5438 | // Use chunk-aware deletion (handles both chunked and non-chunked content) |
| @@ -5452,36 +5440,56 @@ | ||
| 5452 | 5440 | |
| 5453 | 5441 | if (is_wp_error($delete_result)) { |
| 5454 | 5442 | //error_log('MXChat: Chunk-aware deletion failed for URL: ' . $source_url . ' - ' . $delete_result->get_error_message()); |
| 5455 | 5443 | } |
| 5444 | +} | |
| 5456 | 5445 | |
| 5457 | - delete_transient('mxchat_prev_url_' . $post_id); | |
| 5458 | - delete_transient('mxchat_prev_status_' . $post_id); | |
| 5459 | -} | |
| 5460 | 5446 | |
| 5461 | -/** | |
| 5462 | - * Resolve the source URL for a post being trashed/deleted. | |
| 5463 | - * | |
| 5464 | - * Why: wp_trash_post appends "__trashed" to the slug before the wp_trash_post action fires, so | |
| 5465 | - * get_permalink() returns a URL whose md5() won't match the vector IDs stored in Pinecone or | |
| 5466 | - * the source_url rows in the WP DB. Prefer the URL captured by mxchat_store_pre_update_status | |
| 5467 | - * (runs on pre_post_update, before the rename); fall back to stripping the __trashed suffix. | |
| 5468 | - */ | |
| 5469 | -private function mxchat_resolve_pre_trash_url($post_id) { | |
| 5470 | - $previous_url = get_transient('mxchat_prev_url_' . $post_id); | |
| 5471 | - if (!empty($previous_url)) { | |
| 5472 | - return $previous_url; | |
| 5473 | - } | |
| 5447 | + /** | |
| 5448 | + * Deletes data from Pinecone using a source URL | |
| 5449 | + */ | |
| 5450 | + public function mxchat_delete_from_pinecone_by_url($source_url, $pinecone_options) { | |
| 5451 | + $host = $pinecone_options['mxchat_pinecone_host'] ?? ''; | |
| 5452 | + $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? ''; | |
| 5474 | 5453 | |
| 5475 | - $current = get_permalink($post_id); | |
| 5476 | - if (!$current) { | |
| 5477 | - return ''; | |
| 5478 | - } | |
| 5479 | - return preg_replace('#__trashed(/?)$#', '$1', $current); | |
| 5480 | -} | |
| 5454 | + if (empty($host) || empty($api_key)) { | |
| 5455 | + //error_log('MXChat: Pinecone deletion failed - missing configuration'); | |
| 5456 | + return false; | |
| 5457 | + } | |
| 5481 | 5458 | |
| 5459 | + $api_endpoint = "https://{$host}/vectors/delete"; | |
| 5460 | + $vector_id = md5($source_url); | |
| 5482 | 5461 | |
| 5462 | + $request_body = array( | |
| 5463 | + 'ids' => array($vector_id) | |
| 5464 | + ); | |
| 5483 | 5465 | |
| 5466 | + $response = wp_remote_post($api_endpoint, array( | |
| 5467 | + 'headers' => array( | |
| 5468 | + 'Api-Key' => $api_key, | |
| 5469 | + 'accept' => 'application/json', | |
| 5470 | + 'content-type' => 'application/json' | |
| 5471 | + ), | |
| 5472 | + 'body' => wp_json_encode($request_body), | |
| 5473 | + 'timeout' => 30 | |
| 5474 | + )); | |
| 5475 | + | |
| 5476 | + if (is_wp_error($response)) { | |
| 5477 | + //error_log('MXChat: Pinecone deletion error - ' . $response->get_error_message()); | |
| 5478 | + return false; | |
| 5479 | + } | |
| 5480 | + | |
| 5481 | + $response_code = wp_remote_retrieve_response_code($response); | |
| 5482 | + if ($response_code !== 200) { | |
| 5483 | + //error_log('MXChat: Pinecone deletion failed with status ' . $response_code); | |
| 5484 | + return false; | |
| 5485 | + } | |
| 5486 | + | |
| 5487 | + return true; | |
| 5488 | + } | |
| 5489 | + | |
| 5490 | + | |
| 5491 | + | |
| 5484 | 5492 | public function mxchat_handle_product_change($post_id, $post, $update) { |
| 5485 | 5493 | if ($post->post_type !== 'product') { |
| 5486 | 5494 | return; |
| 5487 | 5495 | } |
| @@ -5633,18 +5641,28 @@ | ||
| 5633 | 5641 | if (get_post_type($post_id) !== 'product') { |
| 5634 | 5642 | return; |
| 5635 | 5643 | } |
| 5636 | 5644 | |
| 5637 | - $source_url = $this->mxchat_resolve_pre_trash_url($post_id); | |
| 5638 | - if (!$source_url) { | |
| 5639 | - return; | |
| 5640 | - } | |
| 5645 | + $source_url = get_permalink($post_id); | |
| 5641 | 5646 | |
| 5642 | - // Chunk-aware deletion (routes to Pinecone or WP DB and removes base + all chunks) | |
| 5643 | - MxChat_Utils::delete_chunks_for_url($source_url, 'default'); | |
| 5647 | + // Check if Pinecone is enabled | |
| 5648 | + $pinecone_options = get_option('mxchat_pinecone_addon_options', array()); | |
| 5649 | + $use_pinecone = ($pinecone_options['mxchat_use_pinecone'] ?? '0') === '1'; | |
| 5644 | 5650 | |
| 5645 | - delete_transient('mxchat_prev_url_' . $post_id); | |
| 5646 | - delete_transient('mxchat_prev_status_' . $post_id); | |
| 5651 | + if ($use_pinecone && !empty($pinecone_options['mxchat_pinecone_api_key'])) { | |
| 5652 | + // Delete from Pinecone | |
| 5653 | + $this->mxchat_delete_from_pinecone_by_url($source_url, $pinecone_options); | |
| 5654 | + } else { | |
| 5655 | + // Delete from WordPress DB | |
| 5656 | + global $wpdb; | |
| 5657 | + $table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; | |
| 5658 | + | |
| 5659 | + $wpdb->delete( | |
| 5660 | + $table_name, | |
| 5661 | + array('source_url' => $source_url), | |
| 5662 | + array('%s') | |
| 5663 | + ); | |
| 5664 | + } | |
| 5647 | 5665 | } |
| 5648 | 5666 | |
| 5649 | 5667 | /** |
| 5650 | 5668 | * Handle individual Pinecone content deletion |