88namespace Activitypub \Handler ;
99
1010use Activitypub \Collection \Interactions ;
11+ use Activitypub \Collection \Posts ;
1112use Activitypub \Collection \Remote_Actors ;
1213use Activitypub \Tombstone ;
1314
15+ use function Activitypub \is_activity_reply ;
1416use function Activitypub \object_to_uri ;
1517
1618/**
@@ -23,7 +25,8 @@ class Delete {
2325 public static function init () {
2426 \add_action ( 'activitypub_inbox_delete ' , array ( self ::class, 'handle_delete ' ), 10 , 2 );
2527 \add_filter ( 'activitypub_defer_signature_verification ' , array ( self ::class, 'defer_signature_verification ' ), 10 , 2 );
26- \add_action ( 'activitypub_delete_actor_interactions ' , array ( self ::class, 'delete_interactions ' ) );
28+ \add_action ( 'activitypub_delete_remote_actor_interactions ' , array ( self ::class, 'delete_interactions ' ) );
29+ \add_action ( 'activitypub_delete_remote_actor_posts ' , array ( self ::class, 'delete_posts ' ) );
2730
2831 \add_filter ( 'activitypub_get_outbox_activity ' , array ( self ::class, 'outbox_activity ' ) );
2932 \add_action ( 'post_activitypub_add_to_outbox ' , array ( self ::class, 'post_add_to_outbox ' ), 10 , 2 );
@@ -37,8 +40,6 @@ public static function init() {
3740 */
3841 public static function handle_delete ( $ activity , $ user_id ) {
3942 $ object_type = $ activity ['object ' ]['type ' ] ?? '' ;
40- $ success = false ;
41- $ result = null ;
4243
4344 switch ( $ object_type ) {
4445 /*
@@ -51,7 +52,7 @@ public static function handle_delete( $activity, $user_id ) {
5152 case 'Organization ' :
5253 case 'Service ' :
5354 case 'Application ' :
54- $ result = self ::maybe_delete_follower ( $ activity );
55+ self ::delete_remote_actor ( $ activity, $ user_id );
5556 break ;
5657
5758 /*
@@ -66,7 +67,7 @@ public static function handle_delete( $activity, $user_id ) {
6667 case 'Video ' :
6768 case 'Event ' :
6869 case 'Document ' :
69- $ result = self ::maybe_delete_interaction ( $ activity );
70+ self ::delete_object ( $ activity, $ user_id );
7071 break ;
7172
7273 /*
@@ -75,7 +76,7 @@ public static function handle_delete( $activity, $user_id ) {
7576 * @see: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tombstone
7677 */
7778 case 'Tombstone ' :
78- $ result = self ::maybe_delete_interaction ( $ activity );
79+ self ::delete_object ( $ activity, $ user_id );
7980 break ;
8081
8182 /*
@@ -84,32 +85,65 @@ public static function handle_delete( $activity, $user_id ) {
8485 * @see https://www.w3.org/TR/activitystreams-core/#example-1
8586 */
8687 default :
87- // Ignore non Minimal Activities.
88- if ( ! is_string ( $ activity ['object ' ] ) ) {
89- return ;
90- }
91-
9288 // Check if Object is an Actor.
93- if ( $ activity ['actor ' ] === $ activity ['object ' ] ) {
94- $ result = self ::maybe_delete_follower ( $ activity );
95- } else { // Assume an interaction otherwise.
96- $ result = self ::maybe_delete_interaction ( $ activity );
89+ if ( object_to_uri ( $ activity ['object ' ] ) === $ activity ['actor ' ] ) {
90+ self ::delete_remote_actor ( $ activity, $ user_id );
91+ } else { // Assume an object otherwise.
92+ self ::delete_object ( $ activity, $ user_id );
9793 }
9894 // Maybe handle Delete Activity for other Object Types.
9995 break ;
10096 }
97+ }
98+
99+ /**
100+ * Delete an Object.
101+ *
102+ * @param array $activity The Activity object.
103+ * @param int $user_id The user ID.
104+ */
105+ public static function delete_object ( $ activity , $ user_id ) {
106+ // Check for private and/or direct messages.
107+ if ( is_activity_reply ( $ activity ) ) {
108+ $ result = self ::maybe_delete_interaction ( $ activity );
109+ } else {
110+ $ result = self ::maybe_delete_post ( $ activity );
111+ }
112+
113+ $ success = ( $ result && ! \is_wp_error ( $ result ) );
114+
115+ /**
116+ * Fires after an ActivityPub Delete activity has been handled.
117+ *
118+ * @param array $activity The ActivityPub activity data.
119+ * @param int $user_id The local user ID.
120+ * @param bool $success True on success, false otherwise.
121+ * @param mixed|null $result The result of the delete operation.
122+ */
123+ \do_action ( 'activitypub_handled_delete ' , $ activity , $ user_id , $ success , $ result );
124+ }
101125
102- $ success = (bool ) $ result ;
126+ /**
127+ * Delete an Actor.
128+ *
129+ * @param array $activity The Activity object.
130+ * @param int $user_id The user ID.
131+ */
132+ public static function delete_remote_actor ( $ activity , $ user_id ) {
133+ $ result = self ::maybe_delete_follower ( $ activity );
134+ $ success = ( $ result && ! \is_wp_error ( $ result ) );
103135
104136 /**
105137 * Fires after an ActivityPub Delete activity has been handled.
106138 *
107139 * @param array $activity The ActivityPub activity data.
108140 * @param int $user_id The local user ID.
109141 * @param bool $success True on success, false otherwise.
110- * @param mixed|null $result The result of the delete operation (e.g., WP_Comment object or deletion status) .
142+ * @param mixed|null $result The result of the delete operation.
111143 */
112144 \do_action ( 'activitypub_handled_delete ' , $ activity , $ user_id , $ success , $ result );
145+
146+ return $ result ;
113147 }
114148
115149 /**
@@ -126,6 +160,7 @@ public static function maybe_delete_follower( $activity ) {
126160 if ( ! is_wp_error ( $ follower ) && Tombstone::exists ( $ activity ['actor ' ] ) ) {
127161 $ state = Remote_Actors::delete ( $ follower ->ID );
128162 self ::maybe_delete_interactions ( $ activity );
163+ self ::maybe_delete_posts ( $ activity );
129164 }
130165
131166 return $ state ?? false ;
@@ -143,7 +178,29 @@ public static function maybe_delete_interactions( $activity ) {
143178 if ( Tombstone::exists ( $ activity ['actor ' ] ) ) {
144179 \wp_schedule_single_event (
145180 \time (),
146- 'activitypub_delete_actor_interactions ' ,
181+ 'activitypub_delete_remote_actor_interactions ' ,
182+ array ( $ activity ['actor ' ] )
183+ );
184+
185+ return true ;
186+ }
187+
188+ return false ;
189+ }
190+
191+ /**
192+ * Delete Reactions if Actor-URL is a Tombstone.
193+ *
194+ * @param array $activity The delete activity.
195+ *
196+ * @return bool True on success, false otherwise.
197+ */
198+ public static function maybe_delete_posts ( $ activity ) {
199+ // Verify that Actor is deleted.
200+ if ( Tombstone::exists ( $ activity ['actor ' ] ) ) {
201+ \wp_schedule_single_event (
202+ \time (),
203+ 'activitypub_delete_remote_actor_posts ' ,
147204 array ( $ activity ['actor ' ] )
148205 );
149206
@@ -164,7 +221,7 @@ public static function delete_interactions( $actor ) {
164221 $ comments = Interactions::get_by_actor ( $ actor );
165222
166223 foreach ( $ comments as $ comment ) {
167- wp_delete_comment ( $ comment , true );
224+ \ wp_delete_comment ( $ comment , true );
168225 }
169226
170227 if ( $ comments ) {
@@ -174,6 +231,27 @@ public static function delete_interactions( $actor ) {
174231 }
175232 }
176233
234+ /**
235+ * Delete comments from an Actor.
236+ *
237+ * @param string $actor The URL of the actor whose comments to delete.
238+ *
239+ * @return bool True on success, false otherwise.
240+ */
241+ public static function delete_posts ( $ actor ) {
242+ $ posts = Posts::get_by_remote_actor ( $ actor );
243+
244+ foreach ( $ posts as $ post ) {
245+ Posts::delete ( $ post ->ID );
246+ }
247+
248+ if ( $ posts ) {
249+ return true ;
250+ } else {
251+ return false ;
252+ }
253+ }
254+
177255 /**
178256 * Delete a Reaction if URL is a Tombstone.
179257 *
@@ -201,6 +279,24 @@ public static function maybe_delete_interaction( $activity ) {
201279 return false ;
202280 }
203281
282+ /**
283+ * Delete a post from the Posts collection.
284+ *
285+ * @param array $activity The delete activity.
286+ *
287+ * @return bool|\WP_Error True on success, false or WP_Error on failure.
288+ */
289+ public static function maybe_delete_post ( $ activity ) {
290+ $ id = object_to_uri ( $ activity ['object ' ] );
291+
292+ // Check if the object exists and is a tombstone.
293+ if ( Tombstone::exists ( $ id ) ) {
294+ return Posts::delete_by_guid ( $ id );
295+ }
296+
297+ return false ;
298+ }
299+
204300 /**
205301 * Defer signature verification for `Delete` requests.
206302 *
0 commit comments