@@ -201,6 +201,13 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
201
201
public const FB_SYNC_TIMEOUT = 30 ;
202
202
public const FB_PRIORITY_MID = 9 ;
203
203
204
+ /**
205
+ * Static flag to prevent infinite loops when updating last change time.
206
+ *
207
+ * @var bool
208
+ */
209
+ private static $ is_updating_last_change_time = false ;
210
+
204
211
/**
205
212
* Facebook exception test mode switch.
206
213
*
@@ -376,6 +383,9 @@ public function __construct( WC_Facebookcommerce $facebook_for_woocommerce ) {
376
383
377
384
// Init Whatsapp Utility Event Processor
378
385
$ this ->wa_utility_event_processor = $ this ->load_whatsapp_utility_event_processor ();
386
+
387
+ // Track programmatic changes that don't update post_modified
388
+ add_action ( 'updated_post_meta ' , array ( $ this , 'update_last_change_time ' ), 10 , 4 );
379
389
}
380
390
381
391
/**
@@ -2110,6 +2120,76 @@ private function should_update_product_change_time( $product_id, $meta_key ) {
2110
2120
return true ;
2111
2121
}
2112
2122
2123
+ /**
2124
+ * Performs the actual last change time update with proper flag management.
2125
+ *
2126
+ * @param int $product_id Product ID.
2127
+ */
2128
+ private function perform_last_change_time_update ( $ product_id ) {
2129
+ // Set flag to prevent infinite loops
2130
+ self ::$ is_updating_last_change_time = true ;
2131
+
2132
+ try {
2133
+ $ current_time = time ();
2134
+
2135
+ // Update the database
2136
+ update_post_meta ( $ product_id , '_last_change_time ' , $ current_time );
2137
+
2138
+ // Update cache for rate limiting
2139
+ $ this ->set_last_change_time_cache ( $ product_id , $ current_time );
2140
+
2141
+ } finally {
2142
+ // Always reset flag, even if update fails
2143
+ self ::$ is_updating_last_change_time = false ;
2144
+ }
2145
+ }
2146
+
2147
+ /**
2148
+ * Updates the _last_change_time meta field when wp_postmeta table is updated.
2149
+ *
2150
+ * @param int $meta_id ID of the metadata entry to update.
2151
+ * @param int $product_id Post ID.
2152
+ * @param string $meta_key Meta key.
2153
+ * @param mixed $meta_value Meta value.
2154
+ * @since 3.5.7
2155
+ */
2156
+ public function update_last_change_time ( $ meta_id , $ product_id , $ meta_key , $ meta_value ) {
2157
+ // Guard against infinite loops
2158
+ if ( self ::$ is_updating_last_change_time ) {
2159
+ return ;
2160
+ }
2161
+
2162
+ try {
2163
+ // Run all validation checks first
2164
+ if ( ! $ this ->should_update_product_change_time ( $ product_id , $ meta_key ) ) {
2165
+ return ;
2166
+ }
2167
+
2168
+ // All checks passed - proceed with update
2169
+ $ this ->perform_last_change_time_update ( $ product_id );
2170
+
2171
+ } catch ( \Exception $ e ) {
2172
+ // Ensure flag is reset even on exception
2173
+ self ::$ is_updating_last_change_time = false ;
2174
+
2175
+ Logger::log (
2176
+ 'Error updating last change time for product ' ,
2177
+ [
2178
+ 'event ' => 'update_last_change_time_error ' ,
2179
+ 'product_id ' => $ product_id ,
2180
+ 'meta_key ' => $ meta_key ,
2181
+ 'meta_id ' => $ meta_id ,
2182
+ ],
2183
+ [
2184
+ 'should_send_log_to_meta ' => false ,
2185
+ 'should_save_log_in_woocommerce ' => true ,
2186
+ 'woocommerce_log_level ' => \WC_Log_Levels::ERROR ,
2187
+ ],
2188
+ $ e
2189
+ );
2190
+ }
2191
+ }
2192
+
2113
2193
/**
2114
2194
* Checks if the last change time update is rate limited for a product.
2115
2195
*
0 commit comments