| @@ -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')); |
| @@ -5181,33 +5184,40 @@ | ||
| 5181 | 5184 | // If the post was previously published but is now not published, remove from knowledge base |
| 5182 | 5185 | if ($previous_status === 'publish' && $post->post_status !== 'publish') { |
| 5183 | 5186 | // Use the stored URL from when it was published, or fall back to current permalink |
| 5184 | 5187 | $source_url = $previous_url ?: get_permalink($post_id); |
| 5188 | + | |
| 5189 | + if ($source_url) { | |
| 5190 | + // Check if Pinecone is enabled | |
| 5191 | + $pinecone_options = get_option('mxchat_pinecone_addon_options', array()); | |
| 5192 | + $use_pinecone = ($pinecone_options['mxchat_use_pinecone'] ?? '0') === '1'; | |
| 5185 | 5193 | |
| 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'); | |
| 5194 | + if ($use_pinecone && !empty($pinecone_options['mxchat_pinecone_api_key'])) { | |
| 5195 | + // Delete from Pinecone | |
| 5196 | + $this->mxchat_delete_from_pinecone_by_url($source_url, $pinecone_options); | |
| 5197 | + } else { | |
| 5198 | + // Delete from WordPress DB | |
| 5199 | + global $wpdb; | |
| 5200 | + $table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; | |
| 5201 | + | |
| 5202 | + $result = $wpdb->delete( | |
| 5203 | + $table_name, | |
| 5204 | + array('source_url' => $source_url), | |
| 5205 | + array('%s') | |
| 5206 | + ); | |
| 5207 | + } | |
| 5189 | 5208 | } |
| 5190 | - | |
| 5209 | + | |
| 5191 | 5210 | // Clean up the transients and exit early |
| 5192 | 5211 | delete_transient($previous_status_key); |
| 5193 | 5212 | delete_transient($previous_url_key); |
| 5194 | 5213 | return; |
| 5195 | 5214 | } |
| 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 | - | |
| 5215 | + | |
| 5206 | 5216 | // Store the current status for next time (if this is an update) |
| 5207 | 5217 | if ($update) { |
| 5208 | 5218 | set_transient($previous_status_key, $post->post_status, DAY_IN_SECONDS); |
| 5209 | - | |
| 5219 | + | |
| 5210 | 5220 | // If the post is currently published, also store its URL |
| 5211 | 5221 | if ($post->post_status === 'publish') { |
| 5212 | 5222 | $current_url = get_permalink($post_id); |
| 5213 | 5223 | set_transient($previous_url_key, $current_url, DAY_IN_SECONDS); |
| @@ -5437,14 +5447,12 @@ | ||
| 5437 | 5447 | if (!$should_sync) { |
| 5438 | 5448 | return; |
| 5439 | 5449 | } |
| 5440 | 5450 | |
| 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); | |
| 5451 | + // Get the URL before post is deleted | |
| 5452 | + $source_url = get_permalink($post_id); | |
| 5445 | 5453 | if (!$source_url) { |
| 5446 | - //error_log('MXChat: Failed to resolve source URL for post ' . $post_id); | |
| 5454 | + //error_log('MXChat: Failed to get permalink for post ' . $post_id); | |
| 5447 | 5455 | return; |
| 5448 | 5456 | } |
| 5449 | 5457 | |
| 5450 | 5458 | // Use chunk-aware deletion (handles both chunked and non-chunked content) |
| @@ -5452,36 +5460,56 @@ | ||
| 5452 | 5460 | |
| 5453 | 5461 | if (is_wp_error($delete_result)) { |
| 5454 | 5462 | //error_log('MXChat: Chunk-aware deletion failed for URL: ' . $source_url . ' - ' . $delete_result->get_error_message()); |
| 5455 | 5463 | } |
| 5464 | +} | |
| 5456 | 5465 | |
| 5457 | - delete_transient('mxchat_prev_url_' . $post_id); | |
| 5458 | - delete_transient('mxchat_prev_status_' . $post_id); | |
| 5459 | -} | |
| 5460 | 5466 | |
| 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 | - } | |
| 5467 | + /** | |
| 5468 | + * Deletes data from Pinecone using a source URL | |
| 5469 | + */ | |
| 5470 | + public function mxchat_delete_from_pinecone_by_url($source_url, $pinecone_options) { | |
| 5471 | + $host = $pinecone_options['mxchat_pinecone_host'] ?? ''; | |
| 5472 | + $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? ''; | |
| 5474 | 5473 | |
| 5475 | - $current = get_permalink($post_id); | |
| 5476 | - if (!$current) { | |
| 5477 | - return ''; | |
| 5478 | - } | |
| 5479 | - return preg_replace('#__trashed(/?)$#', '$1', $current); | |
| 5480 | -} | |
| 5474 | + if (empty($host) || empty($api_key)) { | |
| 5475 | + //error_log('MXChat: Pinecone deletion failed - missing configuration'); | |
| 5476 | + return false; | |
| 5477 | + } | |
| 5481 | 5478 | |
| 5479 | + $api_endpoint = "https://{$host}/vectors/delete"; | |
| 5480 | + $vector_id = md5($source_url); | |
| 5482 | 5481 | |
| 5482 | + $request_body = array( | |
| 5483 | + 'ids' => array($vector_id) | |
| 5484 | + ); | |
| 5483 | 5485 | |
| 5486 | + $response = wp_remote_post($api_endpoint, array( | |
| 5487 | + 'headers' => array( | |
| 5488 | + 'Api-Key' => $api_key, | |
| 5489 | + 'accept' => 'application/json', | |
| 5490 | + 'content-type' => 'application/json' | |
| 5491 | + ), | |
| 5492 | + 'body' => wp_json_encode($request_body), | |
| 5493 | + 'timeout' => 30 | |
| 5494 | + )); | |
| 5495 | + | |
| 5496 | + if (is_wp_error($response)) { | |
| 5497 | + //error_log('MXChat: Pinecone deletion error - ' . $response->get_error_message()); | |
| 5498 | + return false; | |
| 5499 | + } | |
| 5500 | + | |
| 5501 | + $response_code = wp_remote_retrieve_response_code($response); | |
| 5502 | + if ($response_code !== 200) { | |
| 5503 | + //error_log('MXChat: Pinecone deletion failed with status ' . $response_code); | |
| 5504 | + return false; | |
| 5505 | + } | |
| 5506 | + | |
| 5507 | + return true; | |
| 5508 | + } | |
| 5509 | + | |
| 5510 | + | |
| 5511 | + | |
| 5484 | 5512 | public function mxchat_handle_product_change($post_id, $post, $update) { |
| 5485 | 5513 | if ($post->post_type !== 'product') { |
| 5486 | 5514 | return; |
| 5487 | 5515 | } |
| @@ -5633,18 +5661,28 @@ | ||
| 5633 | 5661 | if (get_post_type($post_id) !== 'product') { |
| 5634 | 5662 | return; |
| 5635 | 5663 | } |
| 5636 | 5664 | |
| 5637 | - $source_url = $this->mxchat_resolve_pre_trash_url($post_id); | |
| 5638 | - if (!$source_url) { | |
| 5639 | - return; | |
| 5640 | - } | |
| 5665 | + $source_url = get_permalink($post_id); | |
| 5641 | 5666 | |
| 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'); | |
| 5667 | + // Check if Pinecone is enabled | |
| 5668 | + $pinecone_options = get_option('mxchat_pinecone_addon_options', array()); | |
| 5669 | + $use_pinecone = ($pinecone_options['mxchat_use_pinecone'] ?? '0') === '1'; | |
| 5644 | 5670 | |
| 5645 | - delete_transient('mxchat_prev_url_' . $post_id); | |
| 5646 | - delete_transient('mxchat_prev_status_' . $post_id); | |
| 5671 | + if ($use_pinecone && !empty($pinecone_options['mxchat_pinecone_api_key'])) { | |
| 5672 | + // Delete from Pinecone | |
| 5673 | + $this->mxchat_delete_from_pinecone_by_url($source_url, $pinecone_options); | |
| 5674 | + } else { | |
| 5675 | + // Delete from WordPress DB | |
| 5676 | + global $wpdb; | |
| 5677 | + $table_name = $wpdb->prefix . 'mxchat_system_prompt_content'; | |
| 5678 | + | |
| 5679 | + $wpdb->delete( | |
| 5680 | + $table_name, | |
| 5681 | + array('source_url' => $source_url), | |
| 5682 | + array('%s') | |
| 5683 | + ); | |
| 5684 | + } | |
| 5647 | 5685 | } |
| 5648 | 5686 | |
| 5649 | 5687 | /** |
| 5650 | 5688 | * Handle individual Pinecone content deletion |