PluginProbe
ActivityPub / 7.7.0
ActivityPub v7.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/class-migration.php +40 -278 9.2.07.7.0 View file →
@@ -10,9 +10,8 @@
10 10 use Activitypub\Collection\Actors;
11 11 use Activitypub\Collection\Extra_Fields;
12 12 use Activitypub\Collection\Followers;
13 13 use Activitypub\Collection\Following;
14 -use Activitypub\Collection\Inbox;
15 14 use Activitypub\Collection\Outbox;
16 15 use Activitypub\Collection\Remote_Actors;
17 16 use Activitypub\Transformer\Factory;
18 17
@@ -32,11 +31,8 @@
32 31 Scheduler::register_async_batch_callback( 'activitypub_update_comment_counts', array( self::class, 'update_comment_counts' ) );
33 32 Scheduler::register_async_batch_callback( 'activitypub_create_post_outbox_items', array( self::class, 'create_post_outbox_items' ) );
34 33 Scheduler::register_async_batch_callback( 'activitypub_create_comment_outbox_items', array( self::class, 'create_comment_outbox_items' ) );
35 34 Scheduler::register_async_batch_callback( 'activitypub_migrate_avatar_to_remote_actors', array( self::class, 'migrate_avatar_to_remote_actors' ) );
36 - Scheduler::register_async_batch_callback( 'activitypub_migrate_actor_emoji', array( self::class, 'migrate_actor_emoji' ) );
37 - Scheduler::register_async_batch_callback( 'activitypub_backfill_statistics', array( Statistics::class, 'backfill_historical_stats' ) );
38 - Scheduler::register_async_batch_callback( 'activitypub_tombstone_migrate', array( self::class, 'migrate_tombstones_to_cpt' ) );
39 35 }
40 36
41 37 /**
42 38 * The current version of the database structure.
@@ -43,9 +39,9 @@
43 39 *
44 40 * @return string The current version.
45 41 */
46 42 public static function get_version() {
47 - return \get_option( 'activitypub_db_version', 0 );
43 + return get_option( 'activitypub_db_version', 0 );
48 44 }
49 45
50 46 /**
51 47 * Locks the database migration process to prevent simultaneous migrations.
@@ -161,16 +157,21 @@
161 157 }
162 158 if ( \version_compare( $version_from_db, '4.7.2', '<' ) ) {
163 159 self::migrate_to_4_7_2();
164 160 }
161 + if ( \version_compare( $version_from_db, '4.7.3', '<' ) ) {
162 + add_action( 'init', 'flush_rewrite_rules', 20 );
163 + }
165 164 if ( \version_compare( $version_from_db, '5.0.0', '<' ) ) {
166 165 Scheduler::register_schedules();
167 166 \wp_schedule_single_event( \time(), 'activitypub_create_post_outbox_items' );
168 167 \wp_schedule_single_event( \time() + 15, 'activitypub_create_comment_outbox_items' );
168 + add_action( 'init', 'flush_rewrite_rules', 20 );
169 169 }
170 170 if ( \version_compare( $version_from_db, '5.4.0', '<' ) ) {
171 171 \wp_schedule_single_event( \time(), 'activitypub_upgrade', array( 'update_actor_json_slashing' ) );
172 172 \wp_schedule_single_event( \time(), 'activitypub_upgrade', array( 'update_comment_author_emails' ) );
173 + \add_action( 'init', 'flush_rewrite_rules', 20 );
173 174 }
174 175 if ( \version_compare( $version_from_db, '5.7.0', '<' ) ) {
175 176 self::delete_mastodon_api_orphaned_extra_fields();
176 177 }
@@ -176,64 +177,45 @@
176 177 }
177 178 if ( \version_compare( $version_from_db, '5.8.0', '<' ) ) {
178 179 self::update_notification_options();
179 180 }
181 +
180 182 if ( \version_compare( $version_from_db, '6.0.0', '<' ) ) {
181 183 self::migrate_followers_to_ap_actor_cpt();
182 184 \wp_schedule_single_event( \time(), 'activitypub_upgrade', array( 'update_actor_json_storage' ) );
183 185 }
186 +
184 187 if ( \version_compare( $version_from_db, '6.0.1', '<' ) ) {
185 188 self::migrate_followers_to_ap_actor_cpt();
186 189 \wp_schedule_single_event( \time(), 'activitypub_upgrade', array( 'update_actor_json_storage' ) );
187 190 }
191 +
188 192 if ( \version_compare( $version_from_db, '7.0.0', '<' ) ) {
189 - \wp_unschedule_hook( 'activitypub_update_followers' );
190 - \wp_unschedule_hook( 'activitypub_cleanup_followers' );
193 + wp_unschedule_hook( 'activitypub_update_followers' );
194 + wp_unschedule_hook( 'activitypub_cleanup_followers' );
191 195
192 196 if ( ! \wp_next_scheduled( 'activitypub_update_remote_actors' ) ) {
193 - \wp_schedule_event( \time(), 'hourly', 'activitypub_update_remote_actors' );
197 + \wp_schedule_event( time(), 'hourly', 'activitypub_update_remote_actors' );
194 198 }
195 199
196 200 if ( ! \wp_next_scheduled( 'activitypub_cleanup_remote_actors' ) ) {
197 - \wp_schedule_event( \time(), 'daily', 'activitypub_cleanup_remote_actors' );
201 + \wp_schedule_event( time(), 'daily', 'activitypub_cleanup_remote_actors' );
198 202 }
199 203 }
204 +
200 205 if ( \version_compare( $version_from_db, '7.3.0', '<' ) ) {
201 206 self::remove_pending_application_user_follow_requests();
202 207 }
208 +
203 209 if ( \version_compare( $version_from_db, '7.5.0', '<' ) ) {
204 210 self::sync_jetpack_following_meta();
205 211 }
212 +
206 213 if ( \version_compare( $version_from_db, '7.6.0', '<' ) ) {
207 214 self::clean_up_inbox();
208 215 \wp_schedule_single_event( \time(), 'activitypub_migrate_avatar_to_remote_actors' );
209 216 }
210 - if ( \version_compare( $version_from_db, '7.9.0', '<' ) ) {
211 - \wp_schedule_single_event( \time(), 'activitypub_migrate_actor_emoji' );
212 - }
213 - if ( \version_compare( $version_from_db, '8.1.0', '<' ) && ! \wp_next_scheduled( 'activitypub_backfill_statistics' ) ) {
214 - // Backfill historical statistics data (delay + jitter to avoid load spikes on hosts running many sites).
215 - \wp_schedule_single_event( \time() + HOUR_IN_SECONDS + \wp_rand( 0, 6 * HOUR_IN_SECONDS ), 'activitypub_backfill_statistics' );
216 - }
217 217
218 - if ( \version_compare( $version_from_db, '8.3.0', '<' ) ) {
219 - if ( ! \wp_next_scheduled( 'activitypub_tombstone_migrate' ) ) {
220 - \wp_schedule_single_event( \time() + MINUTE_IN_SECONDS, 'activitypub_tombstone_migrate' );
221 - }
222 - }
223 - if ( \version_compare( $version_from_db, '9.1.0', '<' ) ) {
224 - self::migrate_application_keypair_option();
225 - self::delete_application_outbox_items();
226 - }
227 -
228 - /*
229 - * Defer the flush to late in the `init` cycle (priority 20). Migration::init
230 - * runs at priority 1, which is earlier than most plugins register their
231 - * rewrite rules. Flushing synchronously here would persist a truncated
232 - * ruleset that omits third-party rules added on `init` at priority 10.
233 - */
234 - \add_action( 'init', array( Activitypub::class, 'flush_rewrite_rules' ), 20 );
235 -
236 218 // Ensure all required cron schedules are registered.
237 219 Scheduler::register_schedules();
238 220
239 221 /*
@@ -302,10 +284,10 @@
302 284 * Updates the DB-schema of the followers-list.
303 285 */
304 286 public static function migrate_from_0_17() {
305 287 // Migrate followers.
306 - foreach ( \get_users( array( 'fields' => 'ID' ) ) as $user_id ) {
307 - $followers = \get_user_meta( $user_id, 'activitypub_followers', true );
288 + foreach ( get_users( array( 'fields' => 'ID' ) ) as $user_id ) {
289 + $followers = get_user_meta( $user_id, 'activitypub_followers', true );
308 290
309 291 if ( $followers ) {
310 292 foreach ( $followers as $actor ) {
311 293 Followers::add( $user_id, $actor );
@@ -311,8 +293,10 @@
311 293 Followers::add( $user_id, $actor );
312 294 }
313 295 }
314 296 }
297 +
298 + Activitypub::flush_rewrite_rules();
315 299 }
316 300
317 301 /**
318 302 * Clear the cache after updating to 1.3.0.
@@ -325,9 +309,9 @@
325 309 )
326 310 );
327 311
328 312 foreach ( $user_ids as $user_id ) {
329 - \wp_cache_delete( \sprintf( Followers::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
313 + wp_cache_delete( sprintf( Followers::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
330 314 }
331 315 }
332 316
333 317 /**
@@ -333,15 +317,15 @@
333 317 /**
334 318 * Unschedule Hooks after updating to 2.0.0.
335 319 */
336 320 private static function migrate_from_2_0_0() {
337 - \wp_clear_scheduled_hook( 'activitypub_send_post_activity' );
338 - \wp_clear_scheduled_hook( 'activitypub_send_update_activity' );
339 - \wp_clear_scheduled_hook( 'activitypub_send_delete_activity' );
321 + wp_clear_scheduled_hook( 'activitypub_send_post_activity' );
322 + wp_clear_scheduled_hook( 'activitypub_send_update_activity' );
323 + wp_clear_scheduled_hook( 'activitypub_send_delete_activity' );
340 324
341 - \wp_unschedule_hook( 'activitypub_send_post_activity' );
342 - \wp_unschedule_hook( 'activitypub_send_update_activity' );
343 - \wp_unschedule_hook( 'activitypub_send_delete_activity' );
325 + wp_unschedule_hook( 'activitypub_send_post_activity' );
326 + wp_unschedule_hook( 'activitypub_send_update_activity' );
327 + wp_unschedule_hook( 'activitypub_send_delete_activity' );
344 328
345 329 $object_type = \get_option( 'activitypub_object_type', ACTIVITYPUB_DEFAULT_OBJECT_TYPE );
346 330 if ( 'article' === $object_type ) {
347 331 \update_option( 'activitypub_object_type', 'wordpress-post-format' );
@@ -360,9 +344,9 @@
360 344 /**
361 345 * Rename DB fields.
362 346 */
363 347 private static function migrate_from_2_6_0() {
364 - \wp_cache_flush();
348 + wp_cache_flush();
365 349
366 350 self::update_usermeta_key( 'activitypub_user_description', 'activitypub_description' );
367 351
368 352 self::update_options_key( 'activitypub_blog_user_description', 'activitypub_blog_description' );
@@ -376,9 +360,9 @@
376 360 private static function migrate_to_4_0_0() {
377 361 $latest_post_id = 0;
378 362
379 363 // Get the ID of the latest blog post and save it to the options table.
380 - $latest_post = \get_posts(
364 + $latest_post = get_posts(
381 365 array(
382 366 'numberposts' => 1,
383 367 'orderby' => 'ID',
384 368 'order' => 'DESC',
@@ -489,9 +473,9 @@
489 473 $followers = $wpdb->get_col(
490 474 $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s", Remote_Actors::POST_TYPE )
491 475 );
492 476 foreach ( $followers as $id ) {
493 - \clean_post_cache( $id );
477 + clean_post_cache( $id );
494 478 }
495 479 }
496 480
497 481 /**
@@ -507,9 +491,9 @@
507 491 global $wpdb;
508 492
509 493 Comment::register_comment_types();
510 494 $comment_types = Comment::get_comment_type_slugs();
511 - $type_inclusion = "AND comment_type IN ('" . \implode( "','", $comment_types ) . "')";
495 + $type_inclusion = "AND comment_type IN ('" . implode( "','", $comment_types ) . "')";
512 496
513 497 // Get and process this batch.
514 498 $post_ids = $wpdb->get_col( // phpcs:ignore WordPress.DB
515 499 $wpdb->prepare(
@@ -523,9 +507,9 @@
523 507 foreach ( $post_ids as $post_id ) {
524 508 \wp_update_comment_count_now( $post_id );
525 509 }
526 510
527 - if ( \count( $post_ids ) === $batch_size ) {
511 + if ( count( $post_ids ) === $batch_size ) {
528 512 // Schedule next batch.
529 513 return array( $batch_size, $offset + $batch_size );
530 514 }
531 515 }
@@ -547,9 +531,9 @@
547 531 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
548 532 'meta_query' => array(
549 533 array(
550 534 'key' => 'activitypub_status',
551 - 'value' => ACTIVITYPUB_OBJECT_STATE_FEDERATED,
535 + 'value' => 'federated',
552 536 ),
553 537 ),
554 538 )
555 539 );
@@ -567,9 +551,9 @@
567 551 self::add_to_outbox( $post, 'Update', $post->post_author, $visibility );
568 552 }
569 553 }
570 554
571 - if ( \count( $posts ) === $batch_size ) {
555 + if ( count( $posts ) === $batch_size ) {
572 556 return array(
573 557 'batch_size' => $batch_size,
574 558 'offset' => $offset + $batch_size,
575 559 );
@@ -594,9 +578,9 @@
594 578 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
595 579 'meta_query' => array(
596 580 array(
597 581 'key' => 'activitypub_status',
598 - 'value' => ACTIVITYPUB_OBJECT_STATE_FEDERATED,
582 + 'value' => 'federated',
599 583 ),
600 584 ),
601 585 )
602 586 );
@@ -604,9 +588,9 @@
604 588 foreach ( $comments as $comment ) {
605 589 self::add_to_outbox( $comment, 'Create', $comment->user_id );
606 590 }
607 591
608 - if ( \count( $comments ) === $batch_size ) {
592 + if ( count( $comments ) === $batch_size ) {
609 593 return array(
610 594 'batch_size' => $batch_size,
611 595 'offset' => $offset + $batch_size,
612 596 );
@@ -700,9 +684,9 @@
700 684 )
701 685 );
702 686 }
703 687
704 - if ( \count( $comments ) === $batch_size ) {
688 + if ( count( $comments ) === $batch_size ) {
705 689 return array(
706 690 'batch_size' => $batch_size,
707 691 'offset' => $offset + $batch_size,
708 692 );
@@ -1034,9 +1018,9 @@
1034 1018 $wpdb->delete(
1035 1019 $wpdb->postmeta,
1036 1020 array(
1037 1021 'meta_key' => '_activitypub_following', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
1038 - 'meta_value' => -1, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
1022 + 'meta_value' => Actors::APPLICATION_USER_ID, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
1039 1023 )
1040 1024 );
1041 1025 }
1042 1026
@@ -1088,9 +1072,9 @@
1088 1072 // phpcs:ignore WordPress.DB.DirectDatabaseQuery
1089 1073 $inbox_ids = $wpdb->get_col(
1090 1074 $wpdb->prepare(
1091 1075 "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s",
1092 - Inbox::POST_TYPE
1076 + \Activitypub\Collection\Inbox::POST_TYPE
1093 1077 )
1094 1078 );
1095 1079
1096 1080 // Delete all inbox items and their metadata.
@@ -1099,121 +1083,8 @@
1099 1083 }
1100 1084 }
1101 1085
1102 1086 /**
1103 - * Migrate URLs from the legacy `activitypub_tombstone_urls` option into the
1104 - * `ap_tombstone` custom post type.
1105 - *
1106 - * Chunked async migration. Locking and rescheduling is handled by
1107 - * Scheduler::async_batch — the callback returns `array( 'batch_size' => N )`
1108 - * to request another run, or `null` when the option is fully drained.
1109 - *
1110 - * Legacy entries are already-normalized strings (no scheme), so we bypass
1111 - * URL validation and insert directly via wp_insert_post.
1112 - *
1113 - * @since 8.3.0
1114 - *
1115 - * @param int $batch_size Optional. Number of URLs to process per call. Default 500.
1116 - * @return array|null Args for the next run, or null when migration is complete.
1117 - */
1118 - public static function migrate_tombstones_to_cpt( $batch_size = 500 ) {
1119 - global $wpdb;
1120 -
1121 - $urls = \get_option( 'activitypub_tombstone_urls', null );
1122 -
1123 - if ( null === $urls || ! \is_array( $urls ) || empty( $urls ) ) {
1124 - \delete_option( 'activitypub_tombstone_urls' );
1125 - return null;
1126 - }
1127 -
1128 - $chunk = \array_slice( $urls, 0, (int) $batch_size );
1129 - $remaining = \array_slice( $urls, (int) $batch_size );
1130 - $progressed = false;
1131 -
1132 - foreach ( $chunk as $normalized ) {
1133 - if ( ! \is_string( $normalized ) || '' === $normalized ) {
1134 - // Drop garbage entries — counts as progress.
1135 - $progressed = true;
1136 - continue;
1137 - }
1138 -
1139 - $hash = \md5( $normalized );
1140 -
1141 - /*
1142 - * Light existence check. `get_page_by_path()` would hydrate a
1143 - * full `WP_Post` per loop iteration; on a large registry that
1144 - * adds up fast. We only need a boolean here.
1145 - */
1146 - $exists = $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
1147 - $wpdb->prepare(
1148 - "SELECT 1 FROM {$wpdb->posts} WHERE post_type = %s AND post_name = %s LIMIT 1",
1149 - Tombstone::POST_TYPE,
1150 - $hash
1151 - )
1152 - );
1153 - if ( $exists ) {
1154 - $progressed = true;
1155 - continue;
1156 - }
1157 -
1158 - /*
1159 - * `guid` is intentionally omitted: the legacy option only kept
1160 - * the normalized (schemeless) form, so we can't reconstruct the
1161 - * original URL. Storing the schemeless string would be mangled
1162 - * by `esc_url()`. Leave WordPress to auto-generate the guid
1163 - * — it's not used for lookups, only for debugging.
1164 - */
1165 - $result = \wp_insert_post(
1166 - array(
1167 - 'post_type' => Tombstone::POST_TYPE,
1168 - 'post_status' => 'publish',
1169 - 'post_name' => $hash,
1170 - 'post_author' => 0,
1171 - ),
1172 - true
1173 - );
1174 -
1175 - if ( \is_wp_error( $result ) || ! $result ) {
1176 - /*
1177 - * Keep failed inserts in the legacy option so the next batch
1178 - * retries them. `Tombstone::exists_local()` still falls back
1179 - * to the option, so the tombstone remains discoverable.
1180 - */
1181 - $remaining[] = $normalized;
1182 - } else {
1183 - $progressed = true;
1184 - }
1185 - }
1186 -
1187 - if ( empty( $remaining ) ) {
1188 - \delete_option( 'activitypub_tombstone_urls' );
1189 - return null;
1190 - }
1191 -
1192 - /*
1193 - * Disable autoload while we drain. The point of the migration is to
1194 - * stop this option from contributing to `alloptions` pressure, so
1195 - * flip the flag immediately rather than waiting for the option to
1196 - * be fully empty before the relief kicks in.
1197 - */
1198 - \update_option( 'activitypub_tombstone_urls', \array_values( $remaining ), false );
1199 -
1200 - /*
1201 - * If nothing in this batch was drained — every insert errored and
1202 - * nothing was already migrated — halt the scheduler so we don't loop
1203 - * forever on a persistent failure. The legacy option still backs
1204 - * exists_local(), so the data isn't lost; an admin can re-trigger
1205 - * the migration via `wp cron event run activitypub_tombstone_migrate`
1206 - * after fixing the underlying cause.
1207 - */
1208 - if ( ! $progressed ) {
1209 - return null;
1210 - }
1211 -
1212 - return array( 'batch_size' => (int) $batch_size );
1213 - }
1214 -
1215 - /**
1216 1087 * Migrate avatar URLs from comment meta to remote actors in batches.
1217 1088 *
1218 1089 * This migration:
1219 1090 * 1. Finds all comments with ActivityPub protocol and avatar_url meta
@@ -1276,9 +1147,9 @@
1276 1147 }
1277 1148 }
1278 1149
1279 1150 // Return batch info if there are more comments to process.
1280 - if ( \count( $comments ) === $batch_size ) {
1151 + if ( count( $comments ) === $batch_size ) {
1281 1152 return array(
1282 1153 'batch_size' => $batch_size,
1283 1154 );
1284 1155 }
@@ -1283,115 +1154,6 @@
1283 1154 );
1284 1155 }
1285 1156
1286 1157 return null;
1287 - }
1288 -
1289 - /**
1290 - * Migrate emoji data from stored actor JSON to post meta.
1291 - *
1292 - * This migration:
1293 - * 1. Finds all remote actor posts without _activitypub_emoji meta
1294 - * 2. Extracts emoji from stored JSON in post_content
1295 - * 3. Stores as _activitypub_emoji post meta
1296 - *
1297 - * @param int $batch_size Optional. Number of actors to process per batch. Default 50.
1298 - * @param int $offset Optional. Offset for pagination. Default 0.
1299 - * @return array|null Array with batch size if there are more actors to process, null otherwise.
1300 - */
1301 - public static function migrate_actor_emoji( $batch_size = 50, $offset = 0 ) {
1302 - $actors = \get_posts(
1303 - array(
1304 - 'post_type' => Remote_Actors::POST_TYPE,
1305 - 'posts_per_page' => $batch_size,
1306 - 'offset' => $offset,
1307 - 'post_status' => 'any',
1308 - 'orderby' => 'ID',
1309 - 'order' => 'ASC',
1310 - )
1311 - );
1312 -
1313 - foreach ( $actors as $actor_post ) {
1314 - if ( empty( $actor_post->post_content ) ) {
1315 - continue;
1316 - }
1317 -
1318 - $actor_data = \json_decode( $actor_post->post_content, true );
1319 - if ( ! $actor_data ) {
1320 - continue;
1321 - }
1322 -
1323 - $emoji_meta = Emoji::prepare_actor_meta( $actor_data );
1324 - if ( ! empty( $emoji_meta['_activitypub_emoji'] ) ) {
1325 - \update_post_meta( $actor_post->ID, '_activitypub_emoji', $emoji_meta['_activitypub_emoji'] );
1326 - }
1327 - }
1328 -
1329 - // Return batch info if there are more actors to process.
1330 - if ( \count( $actors ) === $batch_size ) {
1331 - return array(
1332 - 'batch_size' => $batch_size,
1333 - 'offset' => $offset + $batch_size,
1334 - );
1335 - }
1336 -
1337 - return null;
1338 - }
1339 -
1340 - /**
1341 - * Migrate the Application key pair option from the old name to the new name.
1342 - *
1343 - * Renames `activitypub_keypair_for_-1` to `activitypub_application_keypair`.
1344 - * Older separate key options (activitypub_application_user_public_key /
1345 - * activitypub_application_user_private_key) are migrated lazily on first read.
1346 - *
1347 - * @since 9.1.0
1348 - */
1349 - public static function migrate_application_keypair_option() {
1350 - self::update_options_key( 'activitypub_keypair_for_-1', Application::KEYPAIR_OPTION_KEY );
1351 -
1352 - // The raw rename bypasses the options API, so drop only the two stale option caches (plus the autoload bucket) instead of flushing everything.
1353 - \wp_cache_delete( 'activitypub_keypair_for_-1', 'options' );
1354 - \wp_cache_delete( Application::KEYPAIR_OPTION_KEY, 'options' );
1355 - \wp_cache_delete( 'alloptions', 'options' );
1356 -
1357 - /*
1358 - * If an early Application::get_keypair() read already created the destination
1359 - * option, the rename above is a no-op blocked by the unique `option_name`,
1360 - * leaving the legacy row behind. Drop it once the destination is in place.
1361 - */
1362 - if ( false !== \get_option( Application::KEYPAIR_OPTION_KEY, false ) ) {
1363 - \delete_option( 'activitypub_keypair_for_-1' );
1364 - }
1365 - }
1366 -
1367 - /**
1368 - * Delete outbox items that belonged to the Application actor.
1369 - *
1370 - * The Application used to queue Reject activities through the Outbox as user
1371 - * ID -1. It no longer dispatches activities, so any pending items are
1372 - * undeliverable and are removed.
1373 - *
1374 - * @since 9.1.0
1375 - */
1376 - public static function delete_application_outbox_items() {
1377 - $items = \get_posts(
1378 - array(
1379 - 'post_type' => Outbox::POST_TYPE,
1380 - 'post_status' => 'any',
1381 - 'nopaging' => true,
1382 - 'fields' => 'ids',
1383 - // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
1384 - 'meta_query' => array(
1385 - array(
1386 - 'key' => '_activitypub_activity_actor',
1387 - 'value' => 'application',
1388 - ),
1389 - ),
1390 - )
1391 - );
1392 -
1393 - foreach ( $items as $item_id ) {
1394 - \wp_delete_post( $item_id, true );
1395 - }
1396 1158 }
1397 1159 }