PluginProbe
ActivityPub / 5.7.0
ActivityPub v5.7.0
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
← All changes | includes/handler/class-delete.php +54 -225 8.2.15.7.0 View file →
@@ -6,12 +6,12 @@
6 6 */
7 7
8 8 namespace Activitypub\Handler;
9 9
10 +use WP_REST_Request;
11 +use Activitypub\Http;
12 +use Activitypub\Collection\Followers;
10 13 use Activitypub\Collection\Interactions;
11 -use Activitypub\Collection\Remote_Actors;
12 -use Activitypub\Collection\Remote_Posts;
13 -use Activitypub\Tombstone;
14 14
15 15 use function Activitypub\object_to_uri;
16 16
17 17 /**
@@ -21,26 +21,21 @@
21 21 /**
22 22 * Initialize the class, registering WordPress hooks.
23 23 */
24 24 public static function init() {
25 - \add_action( 'activitypub_inbox_delete', array( self::class, 'handle_delete' ), 10, 2 );
26 - \add_filter( 'activitypub_skip_inbox_storage', array( self::class, 'skip_inbox_storage' ), 10, 2 );
27 - \add_filter( 'activitypub_defer_signature_verification', array( self::class, 'defer_signature_verification' ), 10, 3 );
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' ) );
30 -
25 + \add_action( 'activitypub_inbox_delete', array( self::class, 'handle_delete' ) );
26 + \add_filter( 'activitypub_defer_signature_verification', array( self::class, 'defer_signature_verification' ), 10, 2 );
27 + \add_action( 'activitypub_delete_actor_interactions', array( self::class, 'delete_interactions' ) );
31 28 \add_filter( 'activitypub_get_outbox_activity', array( self::class, 'outbox_activity' ) );
32 - \add_action( 'post_activitypub_add_to_outbox', array( self::class, 'maybe_bury' ), 10, 2 );
33 29 }
34 30
35 31 /**
36 32 * Handles "Delete" requests.
37 33 *
38 - * @param array $activity The delete activity.
39 - * @param int|int[] $user_ids The local user ID(s).
34 + * @param array $activity The delete activity.
40 35 */
41 - public static function handle_delete( $activity, $user_ids ) {
42 - $object_type = $activity['object']['type'] ?? '';
36 + public static function handle_delete( $activity ) {
37 + $object_type = isset( $activity['object']['type'] ) ? $activity['object']['type'] : '';
43 38
44 39 switch ( $object_type ) {
45 40 /*
46 41 * Actor Types.
@@ -51,9 +46,9 @@
51 46 case 'Group':
52 47 case 'Organization':
53 48 case 'Service':
54 49 case 'Application':
55 - self::delete_remote_actor( $activity, $user_ids );
50 + self::maybe_delete_follower( $activity );
56 51 break;
57 52
58 53 /*
59 54 * Object and Link Types.
@@ -66,9 +61,9 @@
66 61 case 'Audio':
67 62 case 'Video':
68 63 case 'Event':
69 64 case 'Document':
70 - self::delete_object( $activity, $user_ids );
65 + self::maybe_delete_interaction( $activity );
71 66 break;
72 67
73 68 /*
74 69 * Tombstone Type.
@@ -75,9 +70,9 @@
75 70 *
76 71 * @see: https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tombstone
77 72 */
78 73 case 'Tombstone':
79 - self::delete_object( $activity, $user_ids );
74 + self::maybe_delete_interaction( $activity );
80 75 break;
81 76
82 77 /*
83 78 * Minimal Activity.
@@ -84,13 +79,18 @@
84 79 *
85 80 * @see https://www.w3.org/TR/activitystreams-core/#example-1
86 81 */
87 82 default:
83 + // Ignore non Minimal Activities.
84 + if ( ! is_string( $activity['object'] ) ) {
85 + return;
86 + }
87 +
88 88 // Check if Object is an Actor.
89 - if ( object_to_uri( $activity['object'] ) === $activity['actor'] ) {
90 - self::delete_remote_actor( $activity, $user_ids );
91 - } else { // Assume an object otherwise.
92 - self::delete_object( $activity, $user_ids );
89 + if ( $activity['actor'] === $activity['object'] ) {
90 + self::maybe_delete_follower( $activity );
91 + } else { // Assume an interaction otherwise.
92 + self::maybe_delete_interaction( $activity );
93 93 }
94 94 // Maybe handle Delete Activity for other Object Types.
95 95 break;
96 96 }
@@ -96,228 +96,82 @@
96 96 }
97 97 }
98 98
99 99 /**
100 - * Delete an Object.
101 - *
102 - * @param array $activity The Activity object.
103 - * @param int|int[] $user_ids The user ID(s).
104 - */
105 - public static function delete_object( $activity, $user_ids ) {
106 - $result = self::maybe_delete_interaction( $activity );
107 -
108 - if ( ! $result ) {
109 - $result = self::maybe_delete_post( $activity );
110 - }
111 -
112 - $success = ( $result && ! \is_wp_error( $result ) );
113 -
114 - /**
115 - * Fires after an ActivityPub Delete activity has been handled.
116 - *
117 - * @param array $activity The ActivityPub activity data.
118 - * @param int[] $user_ids The local user IDs.
119 - * @param bool $success True on success, false otherwise.
120 - * @param mixed|null $result The result of the delete operation.
121 - */
122 - \do_action( 'activitypub_handled_delete', $activity, (array) $user_ids, $success, $result );
123 - }
124 -
125 - /**
126 - * Delete an Actor.
127 - *
128 - * @param array $activity The Activity object.
129 - * @param int|int[] $user_ids The user ID(s).
130 - */
131 - public static function delete_remote_actor( $activity, $user_ids ) {
132 - $result = self::maybe_delete_follower( $activity );
133 - $success = ( $result && ! \is_wp_error( $result ) );
134 -
135 - /**
136 - * Fires after an ActivityPub Delete activity has been handled.
137 - *
138 - * @param array $activity The ActivityPub activity data.
139 - * @param int[] $user_ids The local user IDs.
140 - * @param bool $success True on success, false otherwise.
141 - * @param mixed|null $result The result of the delete operation.
142 - */
143 - \do_action( 'activitypub_handled_delete', $activity, (array) $user_ids, $success, $result );
144 -
145 - return $result;
146 - }
147 -
148 - /**
149 100 * Delete a Follower if Actor-URL is a Tombstone.
150 101 *
151 102 * @param array $activity The delete activity.
152 - *
153 - * @return bool True on success, false otherwise.
154 103 */
155 104 public static function maybe_delete_follower( $activity ) {
156 - $follower = Remote_Actors::get_by_uri( $activity['actor'] );
105 + /* @var \Activitypub\Model\Follower $follower Follower object. */
106 + $follower = Followers::get_follower_by_actor( $activity['actor'] );
157 107
158 108 // Verify that Actor is deleted.
159 - if ( ! is_wp_error( $follower ) && Tombstone::exists( $activity['actor'] ) ) {
160 - self::maybe_delete_interactions( $follower->ID );
161 - self::maybe_delete_posts( $follower->ID );
162 - $state = Remote_Actors::delete( $follower->ID );
109 + if ( $follower && Http::is_tombstone( $activity['actor'] ) ) {
110 + $follower->delete();
111 + self::maybe_delete_interactions( $activity );
163 112 }
164 -
165 - return $state ?? false;
166 113 }
167 114
168 115 /**
169 - * Schedule Deletion of Interactions of a Remote Actor.
116 + * Delete Reactions if Actor-URL is a Tombstone.
170 117 *
171 - * @param int $id The remote actor ID.
118 + * @param array $activity The delete activity.
172 119 */
173 - public static function maybe_delete_interactions( $id ) {
174 - \wp_schedule_single_event(
175 - \time(),
176 - 'activitypub_delete_remote_actor_interactions',
177 - array( $id )
178 - );
120 + public static function maybe_delete_interactions( $activity ) {
121 + // Verify that Actor is deleted.
122 + if ( Http::is_tombstone( $activity['actor'] ) ) {
123 + \wp_schedule_single_event(
124 + \time(),
125 + 'activitypub_delete_actor_interactions',
126 + array( $activity['actor'] )
127 + );
128 + }
179 129 }
180 130
181 131 /**
182 - * Schedule Deletion of Reader Items of a Remote Actor.
132 + * Delete comments from an Actor.
183 133 *
184 - * @param int $id The remote actor ID.
134 + * @param string $actor The URL of the actor whose comments to delete.
185 135 */
186 - public static function maybe_delete_posts( $id ) {
187 - \wp_schedule_single_event(
188 - \time(),
189 - 'activitypub_delete_remote_actor_posts',
190 - array( $id )
191 - );
192 - }
136 + public static function delete_interactions( $actor ) {
137 + $comments = Interactions::get_interactions_by_actor( $actor );
193 138
194 - /**
195 - * Delete Interactions from a Remote Actor.
196 - *
197 - * @param int $id The ID of the actor whose comments to delete.
198 - *
199 - * @return bool True on success, false otherwise.
200 - */
201 - public static function delete_interactions( $id ) {
202 - $comments = Interactions::get_by_remote_actor_id( $id );
203 -
204 139 foreach ( $comments as $comment ) {
205 - \wp_delete_comment( $comment, true );
140 + wp_delete_comment( $comment, true );
206 141 }
207 -
208 - if ( $comments ) {
209 - return true;
210 - } else {
211 - return false;
212 - }
213 142 }
214 143
215 144 /**
216 - * Delete Reader Items from an Actor.
145 + * Delete a Reaction if URL is a Tombstone.
217 146 *
218 - * @param int $id The ID of the actor whose comments to delete.
219 - *
220 - * @return bool True on success, false otherwise.
147 + * @param array $activity The delete activity.
221 148 */
222 - public static function delete_posts( $id ) {
223 - $posts = Remote_Posts::get_by_remote_actor_id( $id );
224 -
225 - foreach ( $posts as $post ) {
226 - Remote_Posts::delete( $post->ID );
227 - }
228 -
229 - if ( $posts ) {
230 - return true;
149 + public static function maybe_delete_interaction( $activity ) {
150 + if ( is_array( $activity['object'] ) ) {
151 + $id = $activity['object']['id'];
231 152 } else {
232 - return false;
153 + $id = $activity['object'];
233 154 }
234 - }
235 155
236 - /**
237 - * Delete a Reaction if URL is a Tombstone.
238 - *
239 - * Note: When comments are deleted, WordPress automatically deletes all associated
240 - * comment meta including _activitypub_remote_actor_id. The remote actor post itself
241 - * is not deleted, as it may be referenced by other comments or may be needed for
242 - * future interactions.
243 - *
244 - * @param array $activity The delete activity.
245 - *
246 - * @return bool True on success, false otherwise.
247 - */
248 - public static function maybe_delete_interaction( $activity ) {
249 - $id = object_to_uri( $activity['object'] );
250 - $comments = Interactions::get_by_id( $id );
156 + $comments = Interactions::get_interaction_by_id( $id );
251 157
252 - if ( $comments && Tombstone::exists( $id ) ) {
158 + if ( $comments && Http::is_tombstone( $id ) ) {
253 159 foreach ( $comments as $comment ) {
254 - // WordPress will automatically delete all comment meta including _activitypub_remote_actor_id.
255 160 wp_delete_comment( $comment->comment_ID, true );
256 161 }
257 -
258 - return true;
259 162 }
260 -
261 - return false;
262 163 }
263 164
264 165 /**
265 - * Delete a post from the Posts collection.
266 - *
267 - * @param array $activity The delete activity.
268 - *
269 - * @return bool|\WP_Error True on success, false or WP_Error on failure.
270 - */
271 - public static function maybe_delete_post( $activity ) {
272 - $id = object_to_uri( $activity['object'] );
273 -
274 - // Check if the object exists and is a tombstone.
275 - if ( Tombstone::exists( $id ) ) {
276 - return Remote_Posts::delete_by_guid( $id );
277 - }
278 -
279 - return false;
280 - }
281 -
282 - /**
283 - * Skip inbox storage for `Delete` requests.
284 - *
285 - * @param bool $skip Whether to skip inbox storage.
286 - * @param array $data The activity data array.
287 - *
288 - * @return bool Whether to skip inbox storage.
289 - */
290 - public static function skip_inbox_storage( $skip, $data ) {
291 - if ( isset( $data['type'] ) && 'Delete' === $data['type'] ) {
292 - return true;
293 - }
294 -
295 - return $skip;
296 - }
297 -
298 - /**
299 166 * Defer signature verification for `Delete` requests.
300 167 *
301 - * Endpoints that opt in to mandatory signing by calling
302 - * `verify_signature( $request, true )` must not be overridden — the
303 - * Delete carve-out is only for the default inbox path where the
304 - * remote actor's keys may legitimately be gone before the Delete
305 - * arrives.
168 + * @param bool $defer Whether to defer signature verification.
169 + * @param WP_REST_Request $request The request object.
306 170 *
307 - * @since 8.2.0 The `$force_signature` parameter is now respected.
308 - *
309 - * @param bool $defer Whether to defer signature verification.
310 - * @param \WP_REST_Request $request The request object.
311 - * @param bool $force_signature Whether the caller has forced signature verification.
312 - *
313 171 * @return bool Whether to defer signature verification.
314 172 */
315 - public static function defer_signature_verification( $defer, $request, $force_signature = false ) {
316 - if ( $force_signature ) {
317 - return $defer;
318 - }
319 -
173 + public static function defer_signature_verification( $defer, $request ) {
320 174 $json = $request->get_json_params();
321 175
322 176 if ( isset( $json['type'] ) && 'Delete' === $json['type'] ) {
323 177 return true;
@@ -322,9 +176,9 @@
322 176 if ( isset( $json['type'] ) && 'Delete' === $json['type'] ) {
323 177 return true;
324 178 }
325 179
326 - return $defer;
180 + return false;
327 181 }
328 182
329 183 /**
330 184 * Set the object to the object ID.
@@ -329,9 +183,8 @@
329 183 /**
330 184 * Set the object to the object ID.
331 185 *
332 186 * @param \Activitypub\Activity\Activity $activity The Activity object.
333 - *
334 187 * @return \Activitypub\Activity\Activity The filtered Activity object.
335 188 */
336 189 public static function outbox_activity( $activity ) {
337 190 if ( 'Delete' === $activity->get_type() ) {
@@ -338,30 +191,6 @@
338 191 $activity->set_object( object_to_uri( $activity->get_object() ) );
339 192 }
340 193
341 194 return $activity;
342 - }
343 -
344 - /**
345 - * Add a URL to the tombstone registry when a Delete activity is sent.
346 - *
347 - * @param int $outbox_id The ID of the outbox activity.
348 - * @param \Activitypub\Activity\Activity $activity The Activity object.
349 - */
350 - public static function maybe_bury( $outbox_id, $activity ) {
351 - if ( 'Delete' !== $activity->get_type() ) {
352 - return;
353 - }
354 -
355 - $object = $activity->get_object();
356 -
357 - if ( ! $object ) {
358 - return;
359 - }
360 -
361 - Tombstone::bury( object_to_uri( $object ) );
362 -
363 - if ( \is_object( $object ) ) {
364 - Tombstone::bury( $object->get_id(), $object->get_url() );
365 - }
366 195 }
367 196 }