@@ -47,6 +47,10 @@ public function register_hooks(): void {
4747 add_action ( 'delete_attachment ' , [ $ this , 'on_media_deleted ' ], 10 , 1 );
4848 add_action ( 'wp_insert_comment ' , [ $ this , 'on_comment_inserted ' ], 10 , 2 );
4949 add_action ( 'transition_comment_status ' , [ $ this , 'on_comment_status ' ], 10 , 3 );
50+
51+ // Smart Cache integration
52+ add_action ( 'graphql_purge ' , [ $ this , 'on_graphql_purge ' ], 10 , 3 );
53+ add_action ( 'wpgraphql_cache_purge_nodes ' , [ $ this , 'on_cache_purge_nodes ' ], 10 , 2 );
5054 }
5155
5256 /**
@@ -179,4 +183,121 @@ public function on_comment_status( $new_status, $old_status, $comment ) {
179183 'new_status ' => $ new_status ,
180184 ] );
181185 }
186+
187+ /**
188+ * Handle WPGraphQL Smart Cache purge events
189+ *
190+ * @param string $key Cache key being purged
191+ * @param string $event Event type (e.g., post_UPDATE)
192+ * @param string $graphql_endpoint GraphQL endpoint URL
193+ */
194+ public function on_graphql_purge ( $ key , $ event , $ graphql_endpoint ) {
195+ // Parse the event to extract post type and action
196+ $ event_parts = explode ( '_ ' , $ event );
197+ if ( count ( $ event_parts ) !== 2 ) {
198+ return ;
199+ }
200+
201+ $ post_type = $ event_parts [0 ];
202+ $ action = strtolower ( $ event_parts [1 ] );
203+
204+ // Map Smart Cache actions to our webhook events
205+ $ event_map = [
206+ 'create ' => 'smart_cache_created ' ,
207+ 'update ' => 'smart_cache_updated ' ,
208+ 'delete ' => 'smart_cache_deleted ' ,
209+ ];
210+
211+ if ( ! isset ( $ event_map [ $ action ] ) ) {
212+ return ;
213+ }
214+
215+ $ webhook_event = $ event_map [ $ action ];
216+
217+ // Build payload with decoded information
218+ $ payload = [
219+ 'cache_key ' => $ key ,
220+ 'key_type ' => $ this ->classify_cache_key ( $ key ),
221+ 'post_type ' => $ post_type ,
222+ 'action ' => $ action ,
223+ 'graphql_endpoint ' => $ graphql_endpoint ,
224+ 'timestamp ' => current_time ( 'c ' ),
225+ ];
226+
227+ // Try to decode the key if it's a Relay global ID
228+ if ( class_exists ( '\GraphQLRelay\Relay ' ) ) {
229+ try {
230+ $ decoded = \GraphQLRelay \Relay::fromGlobalId ( $ key );
231+ if ( ! empty ( $ decoded ['type ' ] ) && ! empty ( $ decoded ['id ' ] ) ) {
232+ $ payload ['decoded_key ' ] = $ decoded ;
233+ $ payload ['object_id ' ] = absint ( $ decoded ['id ' ] );
234+
235+ // Add object details based on type
236+ if ( $ decoded ['type ' ] === 'post ' && $ action !== 'delete ' ) {
237+ $ post = get_post ( $ decoded ['id ' ] );
238+ if ( $ post ) {
239+ $ payload ['object ' ] = [
240+ 'id ' => $ post ->ID ,
241+ 'title ' => $ post ->post_title ,
242+ 'status ' => $ post ->post_status ,
243+ 'type ' => $ post ->post_type ,
244+ 'url ' => get_permalink ( $ post ),
245+ ];
246+ }
247+ }
248+ }
249+ } catch ( \Exception $ e ) {
250+ // Not a valid Relay ID, continue without decoding
251+ }
252+ }
253+
254+ $ this ->trigger_webhooks ( $ webhook_event , $ payload );
255+ }
256+
257+ /**
258+ * Handle WPGraphQL cache purge nodes event
259+ *
260+ * @param string $key Cache key
261+ * @param array $nodes Nodes being purged
262+ */
263+ public function on_cache_purge_nodes ( $ key , $ nodes ) {
264+ $ payload = [
265+ 'cache_key ' => $ key ,
266+ 'nodes ' => $ nodes ,
267+ 'nodes_count ' => count ( $ nodes ),
268+ 'timestamp ' => current_time ( 'c ' ),
269+ ];
270+
271+ $ this ->trigger_webhooks ( 'smart_cache_nodes_purged ' , $ payload );
272+ }
273+
274+ /**
275+ * Classify the type of cache key
276+ *
277+ * @param string $key Cache key
278+ * @return string
279+ */
280+ private function classify_cache_key ( string $ key ): string {
281+ if ( strpos ( $ key , 'list: ' ) === 0 ) {
282+ return 'list ' ;
283+ }
284+
285+ if ( strpos ( $ key , 'skipped: ' ) === 0 ) {
286+ return 'skipped ' ;
287+ }
288+
289+ // Check if it's a Relay ID
290+ if ( class_exists ( '\GraphQLRelay\Relay ' ) ) {
291+ try {
292+ $ decoded = \GraphQLRelay \Relay::fromGlobalId ( $ key );
293+ if ( ! empty ( $ decoded ['type ' ] ) && ! empty ( $ decoded ['id ' ] ) ) {
294+ return 'relay_id ' ;
295+ }
296+ } catch ( \Exception $ e ) {
297+ // Not a valid Relay ID
298+ }
299+ }
300+
301+ return 'unknown ' ;
302+ }
182303}
0 commit comments