PluginProbe
ActivityPub / 5.3.2
ActivityPub v5.3.2
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
activitypub / includes / class-migration.php

class-migration.php in ActivityPub 5.3.2, at includes/class-migration.php

765 lines 21.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Migration class file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub;
9
10 use Activitypub\Collection\Actors;
11 use Activitypub\Collection\Followers;
12 use Activitypub\Collection\Outbox;
13 use Activitypub\Transformer\Factory;
14
15 /**
16 * ActivityPub Migration Class
17 *
18 * @author Matthias Pfefferle
19 */
20 class Migration {
21 /**
22 * Initialize the class, registering WordPress hooks.
23 */
24 public static function init() {
25 \add_action( 'activitypub_migrate', array( self::class, 'async_migration' ) );
26 \add_action( 'activitypub_upgrade', array( self::class, 'async_upgrade' ), 10, 99 );
27 \add_action( 'activitypub_update_comment_counts', array( self::class, 'update_comment_counts' ), 10, 2 );
28
29 self::maybe_migrate();
30 }
31
32 /**
33 * Get the target version.
34 *
35 * This is the version that the database structure will be updated to.
36 * It is the same as the plugin version.
37 *
38 * @deprecated 4.2.0 Use constant ACTIVITYPUB_PLUGIN_VERSION directly.
39 *
40 * @return string The target version.
41 */
42 public static function get_target_version() {
43 _deprecated_function( __FUNCTION__, '4.2.0', 'ACTIVITYPUB_PLUGIN_VERSION' );
44
45 return ACTIVITYPUB_PLUGIN_VERSION;
46 }
47
48 /**
49 * The current version of the database structure.
50 *
51 * @return string The current version.
52 */
53 public static function get_version() {
54 return get_option( 'activitypub_db_version', 0 );
55 }
56
57 /**
58 * Locks the database migration process to prevent simultaneous migrations.
59 *
60 * @return bool|int True if the lock was successful, timestamp of existing lock otherwise.
61 */
62 public static function lock() {
63 global $wpdb;
64
65 // Try to lock.
66 $lock_result = (bool) $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'no') /* LOCK */", 'activitypub_migration_lock', \time() ) ); // phpcs:ignore WordPress.DB
67
68 if ( ! $lock_result ) {
69 $lock_result = \get_option( 'activitypub_migration_lock' );
70 }
71
72 return $lock_result;
73 }
74
75 /**
76 * Unlocks the database migration process.
77 */
78 public static function unlock() {
79 \delete_option( 'activitypub_migration_lock' );
80 }
81
82 /**
83 * Whether the database migration process is locked.
84 *
85 * @return boolean
86 */
87 public static function is_locked() {
88 $lock = \get_option( 'activitypub_migration_lock' );
89
90 if ( ! $lock ) {
91 return false;
92 }
93
94 $lock = (int) $lock;
95
96 if ( $lock < \time() - 1800 ) {
97 self::unlock();
98 return false;
99 }
100
101 return true;
102 }
103
104 /**
105 * Whether the database structure is up to date.
106 *
107 * @return bool True if the database structure is up to date, false otherwise.
108 */
109 public static function is_latest_version() {
110 return (bool) \version_compare(
111 self::get_version(),
112 ACTIVITYPUB_PLUGIN_VERSION,
113 '=='
114 );
115 }
116
117 /**
118 * Updates the database structure if necessary.
119 */
120 public static function maybe_migrate() {
121 if ( self::is_latest_version() ) {
122 return;
123 }
124
125 if ( self::is_locked() ) {
126 return;
127 }
128
129 self::lock();
130
131 $version_from_db = self::get_version();
132
133 // Check for initial migration.
134 if ( ! $version_from_db ) {
135 self::add_default_settings();
136 $version_from_db = ACTIVITYPUB_PLUGIN_VERSION;
137 }
138
139 // Schedule the async migration.
140 if ( ! \wp_next_scheduled( 'activitypub_migrate', $version_from_db ) ) {
141 \wp_schedule_single_event( \time(), 'activitypub_migrate', array( $version_from_db ) );
142 }
143 if ( \version_compare( $version_from_db, '0.17.0', '<' ) ) {
144 self::migrate_from_0_16();
145 }
146 if ( \version_compare( $version_from_db, '1.3.0', '<' ) ) {
147 self::migrate_from_1_2_0();
148 }
149 if ( \version_compare( $version_from_db, '2.1.0', '<' ) ) {
150 self::migrate_from_2_0_0();
151 }
152 if ( \version_compare( $version_from_db, '2.3.0', '<' ) ) {
153 self::migrate_from_2_2_0();
154 }
155 if ( \version_compare( $version_from_db, '3.0.0', '<' ) ) {
156 self::migrate_from_2_6_0();
157 }
158 if ( \version_compare( $version_from_db, '4.0.0', '<' ) ) {
159 self::migrate_to_4_0_0();
160 }
161 if ( \version_compare( $version_from_db, '4.1.0', '<' ) ) {
162 self::migrate_to_4_1_0();
163 }
164 if ( \version_compare( $version_from_db, '4.5.0', '<' ) ) {
165 \wp_schedule_single_event( \time() + MINUTE_IN_SECONDS, 'activitypub_update_comment_counts' );
166 }
167 if ( \version_compare( $version_from_db, '4.7.1', '<' ) ) {
168 self::migrate_to_4_7_1();
169 }
170 if ( \version_compare( $version_from_db, '4.7.2', '<' ) ) {
171 self::migrate_to_4_7_2();
172 }
173 if ( \version_compare( $version_from_db, '4.7.3', '<' ) ) {
174 add_action( 'init', 'flush_rewrite_rules', 20 );
175 }
176 if ( \version_compare( $version_from_db, '5.0.0', '<' ) ) {
177 Scheduler::register_schedules();
178 \wp_schedule_single_event( \time(), 'activitypub_upgrade', array( 'create_post_outbox_items' ) );
179 \wp_schedule_single_event( \time() + 15, 'activitypub_upgrade', array( 'create_comment_outbox_items' ) );
180 add_action( 'init', 'flush_rewrite_rules', 20 );
181 }
182 if ( \version_compare( $version_from_db, '5.2.0', '<' ) ) {
183 Scheduler::register_schedules();
184 }
185 if ( \version_compare( $version_from_db, '5.3.0', '<' ) ) {
186 add_action( 'init', 'flush_rewrite_rules', 20 );
187 }
188
189 /*
190 * Add new update routines above this comment. ^
191 *
192 * Use 'unreleased' as the version number for new migrations and add tests for the callback directly.
193 * The release script will automatically replace it with the actual version number.
194 * Example:
195 *
196 * if ( \version_compare( $version_from_db, 'unreleased', '<' ) ) {
197 * // Update routine.
198 * }
199 */
200
201 /**
202 * Fires when the system has to be migrated.
203 *
204 * @param string $version_from_db The version from which to migrate.
205 * @param string $target_version The target version to migrate to.
206 */
207 \do_action( 'activitypub_migrate', $version_from_db, ACTIVITYPUB_PLUGIN_VERSION );
208
209 \update_option( 'activitypub_db_version', ACTIVITYPUB_PLUGIN_VERSION );
210
211 self::unlock();
212 }
213
214 /**
215 * Asynchronously migrates the database structure.
216 *
217 * @param string $version_from_db The version from which to migrate.
218 */
219 public static function async_migration( $version_from_db ) {
220 if ( \version_compare( $version_from_db, '1.0.0', '<' ) ) {
221 self::migrate_from_0_17();
222 }
223 }
224
225 /**
226 * Asynchronously runs upgrade routines.
227 *
228 * @param callable $callback Callable upgrade routine. Must be a method of this class.
229 * @params mixed ...$args Optional. Parameters that get passed to the callback.
230 */
231 public static function async_upgrade( $callback ) {
232 $args = \func_get_args();
233
234 // Bail if the existing lock is still valid.
235 if ( self::is_locked() ) {
236 \wp_schedule_single_event( time() + MINUTE_IN_SECONDS, 'activitypub_upgrade', $args );
237 return;
238 }
239
240 self::lock();
241
242 $callback = array_shift( $args ); // Remove $callback from arguments.
243 $next = \call_user_func_array( array( self::class, $callback ), $args );
244
245 self::unlock();
246
247 if ( ! empty( $next ) ) {
248 // Schedule the next run, adding the result to the arguments.
249 \wp_schedule_single_event(
250 \time() + 30,
251 'activitypub_upgrade',
252 \array_merge( array( $callback ), \array_values( $next ) )
253 );
254 }
255 }
256
257 /**
258 * Updates the custom template to use shortcodes instead of the deprecated templates.
259 */
260 private static function migrate_from_0_16() {
261 // Get the custom template.
262 $old_content = \get_option( 'activitypub_custom_post_content', ACTIVITYPUB_CUSTOM_POST_CONTENT );
263
264 /*
265 * If the old content exists but is a blank string, we're going to need a flag to updated it even
266 * after setting it to the default contents.
267 */
268 $need_update = false;
269
270 // If the old contents is blank, use the defaults.
271 if ( '' === $old_content ) {
272 $old_content = ACTIVITYPUB_CUSTOM_POST_CONTENT;
273 $need_update = true;
274 }
275
276 // Set the new content to be the old content.
277 $content = $old_content;
278
279 // Convert old templates to shortcodes.
280 $content = \str_replace( '%title%', '[ap_title]', $content );
281 $content = \str_replace( '%excerpt%', '[ap_excerpt]', $content );
282 $content = \str_replace( '%content%', '[ap_content]', $content );
283 $content = \str_replace( '%permalink%', '[ap_permalink type="html"]', $content );
284 $content = \str_replace( '%shortlink%', '[ap_shortlink type="html"]', $content );
285 $content = \str_replace( '%hashtags%', '[ap_hashtags]', $content );
286 $content = \str_replace( '%tags%', '[ap_hashtags]', $content );
287
288 // Store the new template if required.
289 if ( $content !== $old_content || $need_update ) {
290 \update_option( 'activitypub_custom_post_content', $content );
291 }
292 }
293
294 /**
295 * Updates the DB-schema of the followers-list.
296 */
297 public static function migrate_from_0_17() {
298 // Migrate followers.
299 foreach ( get_users( array( 'fields' => 'ID' ) ) as $user_id ) {
300 $followers = get_user_meta( $user_id, 'activitypub_followers', true );
301
302 if ( $followers ) {
303 foreach ( $followers as $actor ) {
304 Followers::add_follower( $user_id, $actor );
305 }
306 }
307 }
308
309 Activitypub::flush_rewrite_rules();
310 }
311
312 /**
313 * Clear the cache after updating to 1.3.0.
314 */
315 private static function migrate_from_1_2_0() {
316 $user_ids = \get_users(
317 array(
318 'fields' => 'ID',
319 'capability__in' => array( 'publish_posts' ),
320 )
321 );
322
323 foreach ( $user_ids as $user_id ) {
324 wp_cache_delete( sprintf( Followers::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
325 }
326 }
327
328 /**
329 * Unschedule Hooks after updating to 2.0.0.
330 */
331 private static function migrate_from_2_0_0() {
332 wp_clear_scheduled_hook( 'activitypub_send_post_activity' );
333 wp_clear_scheduled_hook( 'activitypub_send_update_activity' );
334 wp_clear_scheduled_hook( 'activitypub_send_delete_activity' );
335
336 wp_unschedule_hook( 'activitypub_send_post_activity' );
337 wp_unschedule_hook( 'activitypub_send_update_activity' );
338 wp_unschedule_hook( 'activitypub_send_delete_activity' );
339
340 $object_type = \get_option( 'activitypub_object_type', ACTIVITYPUB_DEFAULT_OBJECT_TYPE );
341 if ( 'article' === $object_type ) {
342 \update_option( 'activitypub_object_type', 'wordpress-post-format' );
343 }
344 }
345
346 /**
347 * Add the ActivityPub capability to all users that can publish posts
348 * Delete old meta to store followers.
349 */
350 private static function migrate_from_2_2_0() {
351 // Add the ActivityPub capability to all users that can publish posts.
352 self::add_activitypub_capability();
353 }
354
355 /**
356 * Rename DB fields.
357 */
358 private static function migrate_from_2_6_0() {
359 wp_cache_flush();
360
361 self::update_usermeta_key( 'activitypub_user_description', 'activitypub_description' );
362
363 self::update_options_key( 'activitypub_blog_user_description', 'activitypub_blog_description' );
364 self::update_options_key( 'activitypub_blog_user_identifier', 'activitypub_blog_identifier' );
365 }
366
367 /**
368 * * Update actor-mode settings.
369 * * Get the ID of the latest blog post and save it to the options table.
370 */
371 private static function migrate_to_4_0_0() {
372 $latest_post_id = 0;
373
374 // Get the ID of the latest blog post and save it to the options table.
375 $latest_post = get_posts(
376 array(
377 'numberposts' => 1,
378 'orderby' => 'ID',
379 'order' => 'DESC',
380 'post_type' => 'any',
381 'post_status' => 'publish',
382 )
383 );
384
385 if ( $latest_post ) {
386 $latest_post_id = $latest_post[0]->ID;
387 }
388
389 \update_option( 'activitypub_last_post_with_permalink_as_id', $latest_post_id );
390
391 $users = \get_users(
392 array(
393 'capability__in' => array( 'activitypub' ),
394 )
395 );
396
397 foreach ( $users as $user ) {
398 $followers = Followers::get_followers( $user->ID );
399
400 if ( $followers ) {
401 \update_user_option( $user->ID, 'activitypub_use_permalink_as_id', '1' );
402 }
403 }
404
405 $followers = Followers::get_followers( Actors::BLOG_USER_ID );
406
407 if ( $followers ) {
408 \update_option( 'activitypub_use_permalink_as_id_for_blog', '1' );
409 }
410
411 self::migrate_actor_mode();
412 }
413
414 /**
415 * Upate to 4.1.0
416 *
417 * * Migrate the `activitypub_post_content_type` to only use `activitypub_custom_post_content`.
418 */
419 public static function migrate_to_4_1_0() {
420 $content_type = \get_option( 'activitypub_post_content_type' );
421
422 switch ( $content_type ) {
423 case 'excerpt':
424 $template = "[ap_excerpt]\n\n[ap_permalink type=\"html\"]";
425 break;
426 case 'title':
427 $template = "[ap_title type=\"html\"]\n\n[ap_permalink type=\"html\"]";
428 break;
429 case 'content':
430 $template = "[ap_content]\n\n[ap_permalink type=\"html\"]\n\n[ap_hashtags]";
431 break;
432 case 'custom':
433 $template = \get_option( 'activitypub_custom_post_content', ACTIVITYPUB_CUSTOM_POST_CONTENT );
434 break;
435 default:
436 $template = ACTIVITYPUB_CUSTOM_POST_CONTENT;
437 break;
438 }
439
440 \update_option( 'activitypub_custom_post_content', $template );
441
442 \delete_option( 'activitypub_post_content_type' );
443
444 $object_type = \get_option( 'activitypub_object_type', false );
445 if ( ! $object_type ) {
446 \update_option( 'activitypub_object_type', 'note' );
447 }
448
449 // Clean up empty visibility meta.
450 global $wpdb;
451 $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
452 "DELETE FROM $wpdb->postmeta
453 WHERE meta_key = 'activitypub_content_visibility'
454 AND (meta_value IS NULL OR meta_value = '')"
455 );
456 }
457
458 /**
459 * Updates post meta keys to be prefixed with an underscore.
460 */
461 public static function migrate_to_4_7_1() {
462 global $wpdb;
463
464 $meta_keys = array(
465 'activitypub_actor_json',
466 'activitypub_canonical_url',
467 'activitypub_errors',
468 'activitypub_inbox',
469 'activitypub_user_id',
470 );
471
472 foreach ( $meta_keys as $meta_key ) {
473 // phpcs:ignore WordPress.DB
474 $wpdb->update( $wpdb->postmeta, array( 'meta_key' => '_' . $meta_key ), array( 'meta_key' => $meta_key ) );
475 }
476 }
477
478 /**
479 * Clears the post cache for Followers, we should have done this in 4.7.1 when we renamed those keys.
480 */
481 public static function migrate_to_4_7_2() {
482 global $wpdb;
483 // phpcs:ignore WordPress.DB
484 $followers = $wpdb->get_col(
485 $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s", Followers::POST_TYPE )
486 );
487 foreach ( $followers as $id ) {
488 clean_post_cache( $id );
489 }
490 }
491
492 /**
493 * Update comment counts for posts in batches.
494 *
495 * @see Comment::pre_wp_update_comment_count_now()
496 * @param int $batch_size Optional. Number of posts to process per batch. Default 100.
497 * @param int $offset Optional. Number of posts to skip. Default 0.
498 */
499 public static function update_comment_counts( $batch_size = 100, $offset = 0 ) {
500 global $wpdb;
501
502 // Bail if the existing lock is still valid.
503 if ( self::is_locked() ) {
504 \wp_schedule_single_event(
505 time() + ( 5 * MINUTE_IN_SECONDS ),
506 'activitypub_update_comment_counts',
507 array(
508 'batch_size' => $batch_size,
509 'offset' => $offset,
510 )
511 );
512 return;
513 }
514
515 self::lock();
516
517 Comment::register_comment_types();
518 $comment_types = Comment::get_comment_type_slugs();
519 $type_inclusion = "AND comment_type IN ('" . implode( "','", $comment_types ) . "')";
520
521 // Get and process this batch.
522 $post_ids = $wpdb->get_col( // phpcs:ignore WordPress.DB
523 $wpdb->prepare(
524 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
525 "SELECT DISTINCT comment_post_ID FROM {$wpdb->comments} WHERE comment_approved = '1' {$type_inclusion} ORDER BY comment_post_ID LIMIT %d OFFSET %d",
526 $batch_size,
527 $offset
528 )
529 );
530
531 foreach ( $post_ids as $post_id ) {
532 \wp_update_comment_count_now( $post_id );
533 }
534
535 if ( count( $post_ids ) === $batch_size ) {
536 // Schedule next batch.
537 \wp_schedule_single_event(
538 time() + MINUTE_IN_SECONDS,
539 'activitypub_update_comment_counts',
540 array(
541 'batch_size' => $batch_size,
542 'offset' => $offset + $batch_size,
543 )
544 );
545 }
546
547 self::unlock();
548 }
549
550 /**
551 * Create outbox items for posts in batches.
552 *
553 * @param int $batch_size Optional. Number of posts to process per batch. Default 50.
554 * @param int $offset Optional. Number of posts to skip. Default 0.
555 * @return array|null Array with batch size and offset if there are more posts to process, null otherwise.
556 */
557 public static function create_post_outbox_items( $batch_size = 50, $offset = 0 ) {
558 $posts = \get_posts(
559 array(
560 // our own `ap_outbox` will be excluded from `any` by virtue of its `exclude_from_search` arg.
561 'post_type' => 'any',
562 'posts_per_page' => $batch_size,
563 'offset' => $offset,
564 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
565 'meta_query' => array(
566 array(
567 'key' => 'activitypub_status',
568 'value' => 'federated',
569 ),
570 ),
571 )
572 );
573
574 // Avoid multiple queries for post meta.
575 \update_postmeta_cache( \wp_list_pluck( $posts, 'ID' ) );
576
577 foreach ( $posts as $post ) {
578 $visibility = \get_post_meta( $post->ID, 'activitypub_content_visibility', true );
579
580 self::add_to_outbox( $post, 'Create', $post->post_author, $visibility );
581
582 // Add Update activity when the post has been modified.
583 if ( $post->post_modified !== $post->post_date ) {
584 self::add_to_outbox( $post, 'Update', $post->post_author, $visibility );
585 }
586 }
587
588 if ( count( $posts ) === $batch_size ) {
589 return array(
590 'batch_size' => $batch_size,
591 'offset' => $offset + $batch_size,
592 );
593 }
594
595 return null;
596 }
597
598 /**
599 * Create outbox items for comments in batches.
600 *
601 * @param int $batch_size Optional. Number of posts to process per batch. Default 50.
602 * @param int $offset Optional. Number of posts to skip. Default 0.
603 * @return array|null Array with batch size and offset if there are more posts to process, null otherwise.
604 */
605 public static function create_comment_outbox_items( $batch_size = 50, $offset = 0 ) {
606 $comments = \get_comments(
607 array(
608 'author__not_in' => array( 0 ), // Limit to comments by registered users.
609 'number' => $batch_size,
610 'offset' => $offset,
611 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
612 'meta_query' => array(
613 array(
614 'key' => 'activitypub_status',
615 'value' => 'federated',
616 ),
617 ),
618 )
619 );
620
621 foreach ( $comments as $comment ) {
622 self::add_to_outbox( $comment, 'Create', $comment->user_id );
623 }
624
625 if ( count( $comments ) === $batch_size ) {
626 return array(
627 'batch_size' => $batch_size,
628 'offset' => $offset + $batch_size,
629 );
630 }
631
632 return null;
633 }
634
635 /**
636 * Set the defaults needed for the plugin to work.
637 *
638 * Add the ActivityPub capability to all users that can publish posts.
639 */
640 public static function add_default_settings() {
641 self::add_activitypub_capability();
642 self::add_notification_defaults();
643 }
644
645 /**
646 * Add an activity to the outbox without federating it.
647 *
648 * @param \WP_Post|\WP_Comment $comment The comment or post object.
649 * @param string $activity_type The type of activity.
650 * @param int $user_id The user ID.
651 * @param string $visibility Optional. The visibility of the content. Default 'public'.
652 */
653 private static function add_to_outbox( $comment, $activity_type, $user_id, $visibility = ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC ) {
654 $transformer = Factory::get_transformer( $comment );
655 if ( ! $transformer || \is_wp_error( $transformer ) ) {
656 return;
657 }
658
659 $activity = $transformer->to_object();
660 if ( ! $activity || \is_wp_error( $activity ) ) {
661 return;
662 }
663
664 // If the user is disabled, fall back to the blog user when available.
665 if ( is_user_disabled( $user_id ) ) {
666 if ( is_user_disabled( Actors::BLOG_USER_ID ) ) {
667 return;
668 } else {
669 $user_id = Actors::BLOG_USER_ID;
670 }
671 }
672
673 $post_id = Outbox::add( $activity, $activity_type, $user_id, $visibility );
674
675 // Immediately set to publish, no federation needed.
676 \wp_publish_post( $post_id );
677 }
678
679 /**
680 * Add the ActivityPub capability to all users that can publish posts.
681 */
682 private static function add_activitypub_capability() {
683 // Get all WP_User objects that can publish posts.
684 $users = \get_users(
685 array(
686 'capability__in' => array( 'publish_posts' ),
687 )
688 );
689
690 // Add ActivityPub capability to all users that can publish posts.
691 foreach ( $users as $user ) {
692 $user->add_cap( 'activitypub' );
693 }
694 }
695
696 /**
697 * Add default notification settings.
698 */
699 private static function add_notification_defaults() {
700 \add_option( 'activitypub_mailer_new_follower', '1' );
701 \add_option( 'activitypub_mailer_new_dm', '1' );
702 }
703
704 /**
705 * Rename meta keys.
706 *
707 * @param string $old_key The old comment meta key.
708 * @param string $new_key The new comment meta key.
709 */
710 private static function update_usermeta_key( $old_key, $new_key ) {
711 global $wpdb;
712
713 $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
714 $wpdb->usermeta,
715 array( 'meta_key' => $new_key ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
716 array( 'meta_key' => $old_key ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
717 array( '%s' ),
718 array( '%s' )
719 );
720 }
721
722 /**
723 * Rename option keys.
724 *
725 * @param string $old_key The old option key.
726 * @param string $new_key The new option key.
727 */
728 private static function update_options_key( $old_key, $new_key ) {
729 global $wpdb;
730
731 $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
732 $wpdb->options,
733 array( 'option_name' => $new_key ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
734 array( 'option_name' => $old_key ), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
735 array( '%s' ),
736 array( '%s' )
737 );
738 }
739
740 /**
741 * Migrate the actor mode settings.
742 */
743 public static function migrate_actor_mode() {
744 $blog_profile = \get_option( 'activitypub_enable_blog_user', '0' );
745 $author_profiles = \get_option( 'activitypub_enable_users', '1' );
746
747 if (
748 '1' === $blog_profile &&
749 '1' === $author_profiles
750 ) {
751 \update_option( 'activitypub_actor_mode', ACTIVITYPUB_ACTOR_AND_BLOG_MODE );
752 } elseif (
753 '1' === $blog_profile &&
754 '1' !== $author_profiles
755 ) {
756 \update_option( 'activitypub_actor_mode', ACTIVITYPUB_BLOG_MODE );
757 } elseif (
758 '1' !== $blog_profile &&
759 '1' === $author_profiles
760 ) {
761 \update_option( 'activitypub_actor_mode', ACTIVITYPUB_ACTOR_MODE );
762 }
763 }
764 }
765