@@ -225,6 +225,13 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
225
225
public const FB_SYNC_TIMEOUT = 30 ;
226
226
public const FB_PRIORITY_MID = 9 ;
227
227
228
+ /**
229
+ * Static flag to prevent infinite loops when updating last change time.
230
+ *
231
+ * @var bool
232
+ */
233
+ private static $ is_updating_last_change_time = false ;
234
+
228
235
/**
229
236
* Facebook exception test mode switch.
230
237
*
@@ -400,6 +407,9 @@ public function __construct( WC_Facebookcommerce $facebook_for_woocommerce ) {
400
407
401
408
// Init Whatsapp Utility Event Processor
402
409
$ this ->wa_utility_event_processor = $ this ->load_whatsapp_utility_event_processor ();
410
+
411
+ // Track programmatic changes that don't update post_modified
412
+ add_action ( 'updated_post_meta ' , array ( $ this , 'update_product_last_change_time ' ), 10 , 4 );
403
413
}
404
414
405
415
/**
@@ -2111,6 +2121,77 @@ private function should_update_product_change_time( $product_id, $meta_key ) {
2111
2121
return true ;
2112
2122
}
2113
2123
2124
+ /**
2125
+ * Performs the actual product last change time update with proper flag management.
2126
+ *
2127
+ * @param int $product_id Product ID.
2128
+ * @since 3.5.8
2129
+ */
2130
+ private function perform_product_last_change_time_update ( $ product_id ) {
2131
+ // Set flag to prevent infinite loops
2132
+ self ::$ is_updating_last_change_time = true ;
2133
+
2134
+ try {
2135
+ $ current_time = time ();
2136
+
2137
+ // Update the database
2138
+ update_post_meta ( $ product_id , '_last_change_time ' , $ current_time );
2139
+
2140
+ // Update cache for rate limiting
2141
+ $ this ->set_last_change_time_cache ( $ product_id , $ current_time );
2142
+
2143
+ } finally {
2144
+ // Always reset flag, even if update fails
2145
+ self ::$ is_updating_last_change_time = false ;
2146
+ }
2147
+ }
2148
+
2149
+ /**
2150
+ * Updates the _last_change_time meta field when wp_postmeta table is updated.
2151
+ *
2152
+ * @param int $meta_id ID of the metadata entry to update.
2153
+ * @param int $product_id Post ID.
2154
+ * @param string $meta_key Meta key.
2155
+ * @param mixed $meta_value Meta value.
2156
+ * @since 3.5.8
2157
+ */
2158
+ public function update_product_last_change_time ( $ meta_id , $ product_id , $ meta_key , $ meta_value ) {
2159
+ // Guard against infinite loops
2160
+ if ( self ::$ is_updating_last_change_time ) {
2161
+ return ;
2162
+ }
2163
+
2164
+ try {
2165
+ // Run all validation checks first
2166
+ if ( ! $ this ->should_update_product_change_time ( $ product_id , $ meta_key ) ) {
2167
+ return ;
2168
+ }
2169
+
2170
+ // All checks passed - proceed with update
2171
+ $ this ->perform_product_last_change_time_update ( $ product_id );
2172
+
2173
+ } catch ( \Exception $ e ) {
2174
+ // Ensure flag is reset even on exception
2175
+ self ::$ is_updating_last_change_time = false ;
2176
+
2177
+ Logger::log (
2178
+ 'Error updating last change time for product ' ,
2179
+ [
2180
+ 'event ' => 'update_last_change_time_error ' ,
2181
+ 'product_id ' => $ product_id ,
2182
+ 'meta_key ' => $ meta_key ,
2183
+ 'meta_id ' => $ meta_id ,
2184
+ ],
2185
+ [
2186
+ 'should_send_log_to_meta ' => false ,
2187
+ 'should_save_log_in_woocommerce ' => true ,
2188
+ 'woocommerce_log_level ' => \WC_Log_Levels::ERROR ,
2189
+ ],
2190
+ $ e
2191
+ );
2192
+ }
2193
+ }
2194
+
2114
2195
/**
2115
2196
* Checks if the last change time update is rate limited for a product.
2116
2197
*
0 commit comments