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/wp-admin/class-admin.php +149 -359 9.3.07.7.0 View file →
@@ -6,17 +6,14 @@
6 6 */
7 7
8 8 namespace Activitypub\WP_Admin;
9 9
10 -use Activitypub\Blocklist_Subscriptions;
11 10 use Activitypub\Collection\Actors;
12 11 use Activitypub\Collection\Extra_Fields;
13 12 use Activitypub\Comment;
13 +use Activitypub\Model\Blog;
14 14 use Activitypub\Moderation;
15 -use Activitypub\OAuth\Client;
16 -use Activitypub\OAuth\Token;
17 15 use Activitypub\Scheduler\Actor;
18 -use Activitypub\Tombstone;
19 16
20 17 use function Activitypub\count_followers;
21 18 use function Activitypub\get_content_visibility;
22 19 use function Activitypub\is_user_type_disabled;
@@ -60,11 +57,8 @@
60 57 \add_action( 'admin_action_activitypub_confirm_removal', array( self::class, 'handle_bulk_actor_delete_page' ) );
61 58
62 59 if ( user_can_activitypub( \get_current_user_id() ) ) {
63 60 \add_action( 'show_user_profile', array( self::class, 'add_profile' ) );
64 - if ( \get_option( 'activitypub_api', false ) ) {
65 - \add_action( 'show_user_profile', array( User_Settings_Fields::class, 'connected_apps_section' ) );
66 - }
67 61 }
68 62
69 63 \add_filter( 'dashboard_glance_items', array( self::class, 'dashboard_glance_items' ) );
70 64 \add_filter( 'plugin_action_links_' . ACTIVITYPUB_PLUGIN_BASENAME, array( self::class, 'add_plugin_settings_link' ) );
@@ -74,19 +68,14 @@
74 68 \add_action( 'tool_box', array( self::class, 'tool_box' ) );
75 69 }
76 70
77 71 \add_action( 'admin_print_scripts-profile.php', array( self::class, 'enqueue_moderation_scripts' ) );
78 - \add_action( 'admin_print_scripts-profile.php', array( self::class, 'enqueue_connected_apps_scripts' ) );
79 72 \add_action( 'admin_print_scripts-settings_page_activitypub', array( self::class, 'enqueue_moderation_scripts' ) );
80 73 \add_action( 'admin_print_footer_scripts-settings_page_activitypub', array( self::class, 'open_help_tab' ) );
81 74
75 + \add_action( 'wp_dashboard_setup', array( self::class, 'add_dashboard_widgets' ) );
76 +
82 77 \add_action( 'wp_ajax_activitypub_moderation_settings', array( self::class, 'ajax_moderation_settings' ) );
83 - \add_action( 'wp_ajax_activitypub_blocklist_subscription', array( self::class, 'ajax_blocklist_subscription' ) );
84 - \add_action( 'wp_ajax_activitypub_register_oauth_client', array( self::class, 'ajax_register_oauth_client' ) );
85 - \add_action( 'wp_ajax_activitypub_delete_oauth_client', array( self::class, 'ajax_delete_oauth_client' ) );
86 - \add_action( 'wp_ajax_activitypub_delete_all_oauth_clients', array( self::class, 'ajax_delete_all_oauth_clients' ) );
87 - \add_action( 'wp_ajax_activitypub_revoke_oauth_token', array( self::class, 'ajax_revoke_oauth_token' ) );
88 - \add_action( 'wp_ajax_activitypub_revoke_all_oauth_tokens', array( self::class, 'ajax_revoke_all_oauth_tokens' ) );
89 78 }
90 79
91 80 /**
92 81 * Display admin menu notices about configuration problems or conflicts.
@@ -91,9 +80,9 @@
91 80 /**
92 81 * Display admin menu notices about configuration problems or conflicts.
93 82 */
94 83 public static function admin_notices() {
95 - $current_screen = \get_current_screen();
84 + $current_screen = get_current_screen();
96 85
97 86 if ( ! $current_screen ) {
98 87 return;
99 88 }
@@ -105,12 +94,12 @@
105 94 \delete_option( 'activitypub_self_destruct_complete' );
106 95 ?>
107 96 <div class="notice notice-success is-dismissible">
108 97 <p>
109 - <strong><?php \esc_html_e( 'ActivityPub Self-Destruct Complete!', 'activitypub' ); ?></strong>
98 + <strong><?php esc_html_e( 'ActivityPub Self-Destruct Complete!', 'activitypub' ); ?></strong>
110 99 </p>
111 100 <p>
112 - <?php \esc_html_e( 'All Delete activities have been successfully sent to the Fediverse. Your blog is no longer discoverable via ActivityPub and all followers have been notified of the deletion.', 'activitypub' ); ?>
101 + <?php esc_html_e( 'All Delete activities have been successfully sent to the Fediverse. Your blog is no longer discoverable via ActivityPub and all followers have been notified of the deletion.', 'activitypub' ); ?>
113 102 </p>
114 103 </div>
115 104 <?php
116 105 }
@@ -118,9 +107,9 @@
118 107 if ( 'edit' === $current_screen->base && Extra_Fields::is_extra_fields_post_type( $current_screen->post_type ) ) {
119 108 ?>
120 109 <div class="notice" style="margin: 0; background: none; border: none; box-shadow: none; padding: 15px 0 0 0; font-size: 14px;">
121 110 <?php
122 - \esc_html_e( 'These are extra fields that are used for your ActivityPub profile. You can use your homepage, social profiles, pronouns, age, anything you want.', 'activitypub' );
111 + esc_html_e( 'These are extra fields that are used for your ActivityPub profile. You can use your homepage, social profiles, pronouns, age, anything you want.', 'activitypub' );
123 112 ?>
124 113 </div>
125 114 <?php
126 115 }
@@ -199,13 +188,13 @@
199 188 /**
200 189 * Render user settings.
201 190 */
202 191 public static function add_profile() {
203 - \wp_enqueue_media();
204 - \wp_enqueue_script( 'activitypub-header-image' );
192 + wp_enqueue_media();
193 + wp_enqueue_script( 'activitypub-header-image' );
205 194
206 - \wp_nonce_field( 'activitypub-user-settings', '_apnonce' );
207 - \do_settings_sections( 'activitypub_user_settings' );
195 + wp_nonce_field( 'activitypub-user-settings', '_apnonce' );
196 + do_settings_sections( 'activitypub_user_settings' );
208 197 }
209 198
210 199 /**
211 200 * Save the user settings.
@@ -218,12 +207,12 @@
218 207 if ( ! isset( $_REQUEST['_apnonce'] ) ) {
219 208 return;
220 209 }
221 210
222 - $nonce = \sanitize_text_field( \wp_unslash( $_REQUEST['_apnonce'] ) );
211 + $nonce = sanitize_text_field( wp_unslash( $_REQUEST['_apnonce'] ) );
223 212 if (
224 - ! \wp_verify_nonce( $nonce, 'activitypub-user-settings' ) ||
225 - ! \current_user_can( 'edit_user', $user_id )
213 + ! wp_verify_nonce( $nonce, 'activitypub-user-settings' ) ||
214 + ! current_user_can( 'edit_user', $user_id )
226 215 ) {
227 216 return;
228 217 }
229 218
@@ -234,9 +223,9 @@
234 223 );
235 224
236 225 foreach ( $textarea_field_user_options as $option ) {
237 226 if ( ! empty( $_POST[ $option ] ) ) {
238 - \update_user_option( $user_id, $option, \sanitize_textarea_field( \wp_unslash( $_POST[ $option ] ) ) );
227 + \update_user_option( $user_id, $option, sanitize_textarea_field( wp_unslash( $_POST[ $option ] ) ) );
239 228 } else {
240 229 \delete_user_option( $user_id, $option );
241 230 }
242 231 }
@@ -247,9 +236,9 @@
247 236 );
248 237
249 238 foreach ( $text_field_user_options as $option ) {
250 239 if ( ! empty( $_POST[ $option ] ) ) {
251 - \update_user_option( $user_id, $option, \sanitize_text_field( \wp_unslash( $_POST[ $option ] ) ) );
240 + \update_user_option( $user_id, $option, sanitize_text_field( wp_unslash( $_POST[ $option ] ) ) );
252 241 } else {
253 242 \delete_user_option( $user_id, $option );
254 243 }
255 244 }
@@ -259,15 +248,12 @@
259 248 'activitypub_hide_social_graph',
260 249 'activitypub_mailer_new_dm',
261 250 'activitypub_mailer_new_follower',
262 251 'activitypub_mailer_new_mention',
263 - 'activitypub_mailer_new_reaction',
264 - 'activitypub_mailer_annual_report',
265 - 'activitypub_mailer_monthly_report',
266 252 );
267 253
268 254 foreach ( $required_user_options as $option ) {
269 - \update_user_option( $user_id, $option, \sanitize_text_field( \wp_unslash( $_POST[ $option ] ?? 0 ) ) );
255 + \update_user_option( $user_id, $option, sanitize_text_field( wp_unslash( $_POST[ $option ] ?? 0 ) ) );
270 256 }
271 257 }
272 258
273 259 /**
@@ -275,11 +261,11 @@
275 261 *
276 262 * @param string $hook_suffix The current page.
277 263 */
278 264 public static function enqueue_scripts( $hook_suffix ) {
279 - \wp_register_script(
265 + wp_register_script(
280 266 'activitypub-header-image',
281 - \plugins_url(
267 + plugins_url(
282 268 'assets/js/activitypub-header-image.js',
283 269 ACTIVITYPUB_PLUGIN_FILE
284 270 ),
285 271 array( 'jquery' ),
@@ -289,17 +275,17 @@
289 275
290 276 // Register and enqueue command palette integration.
291 277 if ( user_can_activitypub( \get_current_user_id() ) || \current_user_can( 'manage_options' ) ) {
292 278 $asset_data = include ACTIVITYPUB_PLUGIN_DIR . 'build/command-palette/plugin.asset.php';
293 - \wp_enqueue_script(
279 + wp_enqueue_script(
294 280 'activitypub-command-palette',
295 - \plugins_url( 'build/command-palette/plugin.js', ACTIVITYPUB_PLUGIN_FILE ),
281 + plugins_url( 'build/command-palette/plugin.js', ACTIVITYPUB_PLUGIN_FILE ),
296 282 $asset_data['dependencies'],
297 283 $asset_data['version'],
298 284 true
299 285 );
300 286
301 - \wp_localize_script(
287 + wp_localize_script(
302 288 'activitypub-command-palette',
303 289 'activitypubCommandPalette',
304 290 array(
305 291 'followingEnabled' => '1' === \get_option( 'activitypub_following_ui', '0' ),
@@ -308,12 +294,12 @@
308 294 )
309 295 );
310 296 }
311 297
312 - if ( false !== \strpos( $hook_suffix, 'activitypub' ) && 'dashboard_page_activitypub-social-web' !== $hook_suffix ) {
313 - \wp_enqueue_style(
298 + if ( false !== strpos( $hook_suffix, 'activitypub' ) ) {
299 + wp_enqueue_style(
314 300 'activitypub-admin-styles',
315 - \plugins_url(
301 + plugins_url(
316 302 'assets/css/activitypub-admin.css',
317 303 ACTIVITYPUB_PLUGIN_FILE
318 304 ),
319 305 array(),
@@ -318,11 +304,11 @@
318 304 ),
319 305 array(),
320 306 ACTIVITYPUB_PLUGIN_VERSION
321 307 );
322 - \wp_enqueue_script(
308 + wp_enqueue_script(
323 309 'activitypub-admin-script',
324 - \plugins_url(
310 + plugins_url(
325 311 'assets/js/activitypub-admin.js',
326 312 ACTIVITYPUB_PLUGIN_FILE
327 313 ),
328 314 array( 'jquery', 'wp-util' ),
@@ -336,11 +322,11 @@
336 322 \wp_enqueue_script( 'updates' );
337 323 }
338 324
339 325 if ( 'index.php' === $hook_suffix ) {
340 - \wp_enqueue_style(
326 + wp_enqueue_style(
341 327 'activitypub-admin-styles',
342 - \plugins_url(
328 + plugins_url(
343 329 'assets/css/activitypub-admin.css',
344 330 ACTIVITYPUB_PLUGIN_FILE
345 331 ),
346 332 array(),
@@ -346,15 +332,8 @@
346 332 array(),
347 333 ACTIVITYPUB_PLUGIN_VERSION
348 334 );
349 335 }
350 -
351 - if ( 'edit-comments.php' === $hook_suffix ) {
352 - \wp_add_inline_style(
353 - 'wp-emoji-styles',
354 - '.column-author img.emoji { float: none; }'
355 - );
356 - }
357 336 }
358 337
359 338 /**
360 339 * Enqueue moderation admin scripts.
@@ -362,70 +341,29 @@
362 341 public static function enqueue_moderation_scripts() {
363 342 \wp_enqueue_script(
364 343 'activitypub-moderation-admin',
365 344 ACTIVITYPUB_PLUGIN_URL . 'assets/js/activitypub-moderation-admin.js',
366 - array( 'jquery', 'wp-util', 'wp-a11y', 'wp-i18n' ),
345 + array( 'jquery', 'wp-util', 'wp-a11y' ),
367 346 ACTIVITYPUB_PLUGIN_VERSION,
368 347 true
369 348 );
370 349
371 - \wp_set_script_translations(
372 - 'activitypub-moderation-admin',
373 - 'activitypub',
374 - ACTIVITYPUB_PLUGIN_DIR . 'languages'
375 - );
376 -
377 350 // Localize script with translations and nonces.
378 351 \wp_localize_script(
379 352 'activitypub-moderation-admin',
380 353 'activitypubModerationL10n',
381 354 array(
382 - 'nonce' => \wp_create_nonce( 'activitypub_moderation_settings' ),
355 + 'enterValue' => \__( 'Please enter a value to block.', 'activitypub' ),
356 + 'addBlockFailed' => \__( 'Failed to add block.', 'activitypub' ),
357 + 'removeBlockFailed' => \__( 'Failed to remove block.', 'activitypub' ),
358 + 'alreadyBlocked' => \__( 'This term is already blocked.', 'activitypub' ),
359 + 'invalidDomain' => \__( 'Please enter a valid domain (e.g., example.com).', 'activitypub' ),
360 + 'nonce' => \wp_create_nonce( 'activitypub_moderation_settings' ),
383 361 )
384 362 );
385 363 }
386 364
387 365 /**
388 - * Enqueue connected apps admin scripts on the profile page.
389 - *
390 - * @since 8.1.0
391 - */
392 - public static function enqueue_connected_apps_scripts() {
393 - \wp_enqueue_script(
394 - 'activitypub-connected-apps',
395 - ACTIVITYPUB_PLUGIN_URL . 'assets/js/activitypub-connected-apps.js',
396 - array( 'jquery' ),
397 - ACTIVITYPUB_PLUGIN_VERSION,
398 - true
399 - );
400 -
401 - \wp_localize_script(
402 - 'activitypub-connected-apps',
403 - 'activitypubConnectedApps',
404 - array(
405 - 'ajaxUrl' => \admin_url( 'admin-ajax.php' ),
406 - 'nonce' => \wp_create_nonce( 'activitypub_connected_apps' ),
407 - 'confirm' => \__( 'Are you sure you want to revoke this application token? This action cannot be undone.', 'activitypub' ),
408 - 'confirmAll' => \__( 'Are you sure you want to revoke all connected applications? This action cannot be undone.', 'activitypub' ),
409 - 'confirmDelete' => \__( 'Are you sure you want to delete this application? This action cannot be undone.', 'activitypub' ),
410 - 'confirmDeleteAll' => \__( 'Are you sure you want to delete all registered applications? This action cannot be undone.', 'activitypub' ),
411 - 'registerError' => \__( 'Failed to register application.', 'activitypub' ),
412 - 'deleteLabel' => \__( 'Delete', 'activitypub' ),
413 - 'dismiss' => \__( 'Dismiss this notice.', 'activitypub' ),
414 - 'clientIdLabel' => \__( 'Your new Client ID:', 'activitypub' ),
415 - 'clientSecretLabel' => \__( 'Your new Client Secret:', 'activitypub' ),
416 - 'copy' => \__( 'Copy', 'activitypub' ),
417 - 'copied' => \__( 'Copied!', 'activitypub' ),
418 - 'saveWarning' => \__( 'Be sure to save this in a safe location. You will not be able to retrieve it.', 'activitypub' ),
419 - 'appRevoked' => \__( 'Application token revoked.', 'activitypub' ),
420 - 'allAppsRevoked' => \__( 'All application tokens revoked.', 'activitypub' ),
421 - 'appDeleted' => \__( 'Application deleted.', 'activitypub' ),
422 - 'allAppsDeleted' => \__( 'All registered applications deleted.', 'activitypub' ),
423 - )
424 - );
425 - }
426 -
427 - /**
428 366 * Hook into the edit_comment functionality.
429 367 *
430 368 * Disables the edit_comment capability for federated comments.
431 369 */
@@ -463,20 +401,20 @@
463 401 public static function edit_post() {
464 402 // Disable the edit_post capability for federated posts.
465 403 \add_filter(
466 404 'user_has_cap',
467 - static function ( $all_caps, $caps, $arg ) {
405 + function ( $all_caps, $caps, $arg ) {
468 406 if ( 'edit_post' !== $arg[0] ) {
469 407 return $all_caps;
470 408 }
471 409
472 - $post = \get_post( $arg[2] );
410 + $post = get_post( $arg[2] );
473 411
474 412 if ( ! Extra_Fields::is_extra_field_post_type( $post->post_type ) ) {
475 413 return $all_caps;
476 414 }
477 415
478 - if ( \get_current_user_id() !== (int) $post->post_author ) {
416 + if ( get_current_user_id() !== (int) $post->post_author ) {
479 417 return false;
480 418 }
481 419
482 420 return $all_caps;
@@ -490,14 +428,14 @@
490 428 * Add ActivityPub specific actions/filters to the post list view.
491 429 */
492 430 public static function list_posts() {
493 431 // Remove all views for the extra fields.
494 - $screen_id = \get_current_screen()->id;
432 + $screen_id = get_current_screen()->id;
495 433
496 - \add_filter(
434 + add_filter(
497 435 "views_{$screen_id}",
498 - static function ( $views ) {
499 - if ( Extra_Fields::is_extra_fields_post_type( \get_current_screen()->post_type ) ) {
436 + function ( $views ) {
437 + if ( Extra_Fields::is_extra_fields_post_type( get_current_screen()->post_type ) ) {
500 438 return array();
501 439 }
502 440
503 441 return $views;
@@ -517,9 +455,9 @@
517 455 if ( was_comment_received( $comment ) ) {
518 456 unset( $actions['edit'], $actions['quickedit'] );
519 457 }
520 458
521 - if ( \in_array( \get_comment_type( $comment ), Comment::get_comment_type_slugs(), true ) ) {
459 + if ( in_array( get_comment_type( $comment ), Comment::get_comment_type_slugs(), true ) ) {
522 460 unset( $actions['reply'] );
523 461 }
524 462
525 463 return $actions;
@@ -534,9 +472,9 @@
534 472 *
535 473 * @return array The columns extended by the activitypub.
536 474 */
537 475 public static function manage_users_columns( $columns ) {
538 - $columns['activitypub'] = \__( 'ActivityPub', 'activitypub' );
476 + $columns['activitypub'] = __( 'ActivityPub', 'activitypub' );
539 477 return $columns;
540 478 }
541 479
542 480 /**
@@ -546,10 +484,10 @@
546 484 *
547 485 * @return array The extended list of column names.
548 486 */
549 487 public static function manage_comment_columns( $columns ) {
550 - $columns['comment_type'] = \esc_attr__( 'Comment-Type', 'activitypub' );
551 - $columns['comment_protocol'] = \esc_attr__( 'Protocol', 'activitypub' );
488 + $columns['comment_type'] = esc_attr__( 'Comment-Type', 'activitypub' );
489 + $columns['comment_protocol'] = esc_attr__( 'Protocol', 'activitypub' );
552 490
553 491 return $columns;
554 492 }
555 493
@@ -563,10 +501,10 @@
563 501 */
564 502 public static function manage_post_columns( $columns, $post_type ) {
565 503 if ( Extra_Fields::is_extra_fields_post_type( $post_type ) ) {
566 504 $after_key = 'title';
567 - $index = \array_search( $after_key, \array_keys( $columns ), true );
568 - $columns = \array_slice( $columns, 0, $index + 1 ) + array( 'extra_field_content' => \esc_attr__( 'Content', 'activitypub' ) ) + $columns;
505 + $index = array_search( $after_key, array_keys( $columns ), true );
506 + $columns = array_slice( $columns, 0, $index + 1 ) + array( 'extra_field_content' => esc_attr__( 'Content', 'activitypub' ) ) + $columns;
569 507 }
570 508
571 509 return $columns;
572 510 }
@@ -577,17 +515,17 @@
577 515 * @param array $column The column to implement.
578 516 * @param int $comment_id The comment id.
579 517 */
580 518 public static function manage_comments_custom_column( $column, $comment_id ) {
581 - if ( 'comment_type' === $column && ! \defined( 'WEBMENTION_PLUGIN_DIR' ) ) {
582 - echo \esc_attr( \ucfirst( \get_comment_type( $comment_id ) ) );
519 + if ( 'comment_type' === $column && ! defined( 'WEBMENTION_PLUGIN_DIR' ) ) {
520 + echo esc_attr( ucfirst( get_comment_type( $comment_id ) ) );
583 521 } elseif ( 'comment_protocol' === $column ) {
584 - $protocol = \get_comment_meta( $comment_id, 'protocol', true );
522 + $protocol = get_comment_meta( $comment_id, 'protocol', true );
585 523
586 524 if ( $protocol ) {
587 - echo \esc_attr( \ucfirst( \str_replace( 'activitypub', 'ActivityPub', $protocol ) ) );
525 + echo esc_attr( ucfirst( str_replace( 'activitypub', 'ActivityPub', $protocol ) ) );
588 526 } else {
589 - \esc_attr_e( 'Local', 'activitypub' );
527 + esc_attr_e( 'Local', 'activitypub' );
590 528 }
591 529 }
592 530 }
593 531
@@ -599,9 +537,9 @@
599 537 * @return array The extended comment types.
600 538 */
601 539 public static function comment_types_dropdown( $types ) {
602 540 foreach ( Comment::get_comment_types() as $comment_type ) {
603 - $types[ $comment_type['type'] ] = \esc_html( $comment_type['label'] );
541 + $types[ $comment_type['type'] ] = esc_html( $comment_type['label'] );
604 542 }
605 543
606 544 return $types;
607 545 }
@@ -620,11 +558,11 @@
620 558 return $output;
621 559 }
622 560
623 561 if ( \user_can( $user_id, 'activitypub' ) ) {
624 - return '<span aria-hidden="true">&#x2713;</span><span class="screen-reader-text">' . \esc_html__( 'ActivityPub enabled for this author', 'activitypub' ) . '</span>';
562 + return '<span aria-hidden="true">&#x2713;</span><span class="screen-reader-text">' . esc_html__( 'ActivityPub enabled for this author', 'activitypub' ) . '</span>';
625 563 } else {
626 - return '<span aria-hidden="true">&#x2717;</span><span class="screen-reader-text">' . \esc_html__( 'ActivityPub disabled for this author', 'activitypub' ) . '</span>';
564 + return '<span aria-hidden="true">&#x2717;</span><span class="screen-reader-text">' . esc_html__( 'ActivityPub disabled for this author', 'activitypub' ) . '</span>';
627 565 }
628 566 }
629 567
630 568 /**
@@ -636,11 +574,11 @@
636 574 * @return void
637 575 */
638 576 public static function manage_posts_custom_column( $column_name, $post_id ) {
639 577 if ( 'extra_field_content' === $column_name ) {
640 - $post = \get_post( $post_id );
578 + $post = get_post( $post_id );
641 579 if ( Extra_Fields::is_extra_fields_post_type( $post->post_type ) ) {
642 - echo \esc_attr( \wp_strip_all_tags( $post->post_content ) );
580 + echo esc_attr( wp_strip_all_tags( $post->post_content ) );
643 581 }
644 582 }
645 583 }
646 584
@@ -651,10 +589,10 @@
651 589 *
652 590 * @return array The extended bulk options.
653 591 */
654 592 public static function user_bulk_options( $actions ) {
655 - $actions['add_activitypub_cap'] = \__( 'Enable for ActivityPub', 'activitypub' );
656 - $actions['remove_activitypub_cap'] = \__( 'Disable for ActivityPub', 'activitypub' );
593 + $actions['add_activitypub_cap'] = __( 'Enable for ActivityPub', 'activitypub' );
594 + $actions['remove_activitypub_cap'] = __( 'Disable for ActivityPub', 'activitypub' );
657 595
658 596 return $actions;
659 597 }
660 598
@@ -676,14 +614,8 @@
676 614 case 'add_activitypub_cap':
677 615 foreach ( $users as $user_id ) {
678 616 $user = new \WP_User( $user_id );
679 617 $user->add_cap( 'activitypub' );
680 -
681 - // Remove user from tombstone registry if they were previously buried.
682 - $actor = Actors::get_by_id( $user_id );
683 - if ( ! \is_wp_error( $actor ) ) {
684 - Tombstone::remove( $actor->get_id(), $actor->get_url() );
685 - }
686 618 }
687 619 return $send_back;
688 620 case 'remove_activitypub_cap':
689 621 $removed_count = 0;
@@ -715,9 +647,9 @@
715 647 );
716 648
717 649 // Add user IDs as separate parameters.
718 650 foreach ( $users as $index => $user_id ) {
719 - $query_args[ \sprintf( 'users[%d]', $index ) ] = \absint( $user_id );
651 + $query_args[ sprintf( 'users[%d]', $index ) ] = absint( $user_id );
720 652 }
721 653
722 654 $confirmation_url = \add_query_arg( $query_args, \admin_url( 'users.php' ) );
723 655
@@ -819,9 +751,9 @@
819 751 * @return string The URL to redirect to.
820 752 */
821 753 public static function process_capability_removal( $users, $remove_from_fediverse, $send_back ) {
822 754 // Normalize fediverse removal parameter.
823 - if ( \is_string( $remove_from_fediverse ) ) {
755 + if ( is_string( $remove_from_fediverse ) ) {
824 756 // Legacy format: 'delete' or 'keep' for all users.
825 757 $delete_all = ( 'delete' === $remove_from_fediverse );
826 758 $users_to_delete = $delete_all ? $users : array();
827 759 } else {
@@ -859,11 +791,11 @@
859 791 public static function dashboard_glance_items( $items ) {
860 792 \add_filter( 'number_format_i18n', '\Activitypub\custom_large_numbers', 10, 2 );
861 793
862 794 if ( user_can_activitypub( \get_current_user_id() ) ) {
863 - $follower_count = \sprintf(
795 + $follower_count = sprintf(
864 796 // translators: %s: number of followers.
865 - \_n(
797 + _n(
866 798 '%s Follower',
867 799 '%s Followers',
868 800 count_followers( \get_current_user_id() ),
869 801 'activitypub'
@@ -869,9 +801,9 @@
869 801 'activitypub'
870 802 ),
871 803 \number_format_i18n( count_followers( \get_current_user_id() ) )
872 804 );
873 - $items['activitypub-followers-user'] = \sprintf(
805 + $items['activitypub-followers-user'] = sprintf(
874 806 '<a class="activitypub-followers" href="%1$s" title="%2$s">%3$s</a>',
875 807 \esc_url( \admin_url( 'users.php?page=activitypub-followers-list' ) ),
876 808 \esc_attr__( 'Your followers', 'activitypub' ),
877 809 \esc_html( $follower_count )
@@ -877,12 +809,12 @@
877 809 \esc_html( $follower_count )
878 810 );
879 811 }
880 812
881 - if ( ! is_user_type_disabled( 'blog' ) && \current_user_can( 'manage_options' ) ) {
882 - $follower_count = \sprintf(
813 + if ( ! is_user_type_disabled( 'blog' ) && current_user_can( 'manage_options' ) ) {
814 + $follower_count = sprintf(
883 815 // translators: %s: number of followers.
884 - \_n(
816 + _n(
885 817 '%s Follower (Blog)',
886 818 '%s Followers (Blog)',
887 819 count_followers( Actors::BLOG_USER_ID ),
888 820 'activitypub'
@@ -888,9 +820,9 @@
888 820 'activitypub'
889 821 ),
890 822 \number_format_i18n( count_followers( Actors::BLOG_USER_ID ) )
891 823 );
892 - $items['activitypub-followers-blog'] = \sprintf(
824 + $items['activitypub-followers-blog'] = sprintf(
893 825 '<a class="activitypub-followers" href="%1$s" title="%2$s">%3$s</a>',
894 826 \esc_url( \admin_url( 'options-general.php?page=activitypub&tab=followers' ) ),
895 827 \esc_attr__( 'The Blog\'s followers', 'activitypub' ),
896 828 \esc_html( $follower_count )
@@ -913,9 +845,9 @@
913 845 public static function row_actions( $actions, $post ) {
914 846 // check if the post is enabled for ActivityPub.
915 847 if (
916 848 ! \post_type_supports( \get_post_type( $post ), 'activitypub' ) ||
917 - ! \in_array( $post->post_status, array( 'pending', 'draft', 'future', 'publish' ), true ) ||
849 + ! in_array( $post->post_status, array( 'pending', 'draft', 'future', 'publish' ), true ) ||
918 850 ! \current_user_can( 'edit_post', $post->ID ) ||
919 851 ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL === get_content_visibility( $post->ID ) ||
920 852 ( site_supports_blocks() && \use_block_editor_for_post_type( $post->post_type ) )
921 853 ) {
@@ -921,11 +853,11 @@
921 853 ) {
922 854 return $actions;
923 855 }
924 856
925 - $preview_url = \add_query_arg( 'activitypub', 'true', \get_preview_post_link( $post ) );
857 + $preview_url = add_query_arg( 'activitypub', 'true', \get_preview_post_link( $post ) );
926 858
927 - $actions['activitypub'] = \sprintf(
859 + $actions['activitypub'] = sprintf(
928 860 '<a href="%s" target="_blank">%s</a>',
929 861 \esc_url( $preview_url ),
930 862 \esc_html__( 'Fediverse Preview ⁂', 'activitypub' )
931 863 );
@@ -958,9 +890,9 @@
958 890 if ( ! isset( $update->upgrade_notice ) ) {
959 891 return;
960 892 }
961 893
962 - echo '<br>' . \wp_strip_all_tags( $update->upgrade_notice ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
894 + echo '<br>' . wp_strip_all_tags( $update->upgrade_notice ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
963 895 }
964 896
965 897 /**
966 898 * Adds meta box on wp-admin/tools.php.
@@ -979,9 +911,9 @@
979 911 // get all tabs registered for the ActivityPub settings page.
980 912 $tabs = \get_current_screen()->get_help_tabs();
981 913 $ids = \array_values( \wp_list_pluck( $tabs, 'id' ) );
982 914 $ids = \array_map(
983 - static function ( $id ) {
915 + function ( $id ) {
984 916 return '#tab-link-' . $id;
985 917 },
986 918 $ids
987 919 );
@@ -1005,8 +937,80 @@
1005 937 <?php
1006 938 }
1007 939
1008 940 /**
941 + * Add Dashboard widgets.
942 + */
943 + public static function add_dashboard_widgets() {
944 + \wp_add_dashboard_widget( 'activitypub_blog', \__( 'ActivityPub Plugin News', 'activitypub' ), array( self::class, 'blog_dashboard_widget' ) );
945 + if ( user_can_activitypub( \get_current_user_id() ) && ! is_user_type_disabled( 'user' ) ) {
946 + \wp_add_dashboard_widget( 'activitypub_profile', \__( 'ActivityPub Author profile', 'activitypub' ), array( self::class, 'profile_dashboard_widget' ) );
947 + }
948 + if ( ! is_user_type_disabled( 'blog' ) ) {
949 + \wp_add_dashboard_widget( 'activitypub_blog_profile', \__( 'ActivityPub Blog profile', 'activitypub' ), array( self::class, 'blogprofile_dashboard_widget' ) );
950 + }
951 + }
952 +
953 + /**
954 + * Add the `ActivityPub.blog` feed as a Dashboard widget.
955 + */
956 + public static function blog_dashboard_widget() {
957 + echo '<div class="rss-widget">';
958 + \wp_widget_rss_output(
959 + array(
960 + 'url' => 'https://activitypub.blog/feed/',
961 + 'items' => 3,
962 + 'show_summary' => 1,
963 + 'show_author' => 0,
964 + 'show_date' => 1,
965 + )
966 + );
967 + echo '</div>';
968 + }
969 +
970 + /**
971 + * Add the ActivityPub Author profile as a Dashboard widget.
972 + */
973 + public static function profile_dashboard_widget() {
974 + $user = Actors::get_by_id( \get_current_user_id() );
975 + ?>
976 + <p>
977 + <?php \esc_html_e( 'People can follow you by using your author name:', 'activitypub' ); ?>
978 + </p>
979 + <p><label for="activitypub-user-identifier"><?php \esc_html_e( 'Username', 'activitypub' ); ?></label><input type="text" class="large-text code" id="activitypub-user-identifier" value="<?php echo \esc_attr( $user->get_webfinger() ); ?>" readonly /></p>
980 + <p><label for="activitypub-user-url"><?php \esc_html_e( 'Profile URL', 'activitypub' ); ?></label><input type="text" class="large-text code" id="activitypub-user-url" value="<?php echo \esc_attr( $user->get_url() ); ?>" readonly /></p>
981 + <p>
982 + <?php \esc_html_e( 'Authors who can not access this settings page will find their username on the "Edit Profile" page.', 'activitypub' ); ?>
983 + <a href="<?php echo \esc_url( \admin_url( '/profile.php#activitypub' ) ); ?>">
984 + <?php \esc_html_e( 'Customize username on "Edit Profile" page.', 'activitypub' ); ?>
985 + </a>
986 + </p>
987 + <?php
988 + }
989 +
990 + /**
991 + * Add the ActivityPub Blog profile as a Dashboard widget.
992 + */
993 + public static function blogprofile_dashboard_widget() {
994 + $user = new Blog();
995 + ?>
996 + <p>
997 + <?php \esc_html_e( 'People can follow your blog by using:', 'activitypub' ); ?>
998 + </p>
999 + <p><label for="activitypub-user-identifier"><?php \esc_html_e( 'Username', 'activitypub' ); ?></label><input type="text" class="large-text code" id="activitypub-user-identifier" value="<?php echo \esc_attr( $user->get_webfinger() ); ?>" readonly /></p>
1000 + <p><label for="activitypub-user-url"><?php \esc_html_e( 'Profile URL', 'activitypub' ); ?></label><input type="text" class="large-text code" id="activitypub-user-url" value="<?php echo \esc_attr( $user->get_url() ); ?>" readonly /></p>
1001 + <p>
1002 + <?php \esc_html_e( 'This blog profile will federate all posts written on your blog, regardless of the author who posted it.', 'activitypub' ); ?>
1003 + <?php if ( current_user_can( 'manage_options' ) ) : ?>
1004 + <a href="<?php echo \esc_url( \admin_url( '/options-general.php?page=activitypub&tab=blog-profile' ) ); ?>">
1005 + <?php \esc_html_e( 'Customize the blog profile.', 'activitypub' ); ?>
1006 + </a>
1007 + <?php endif; ?>
1008 + </p>
1009 + <?php
1010 + }
1011 +
1012 + /**
1009 1013 * AJAX handler for moderation settings (add/remove blocks).
1010 1014 */
1011 1015 public static function ajax_moderation_settings() {
1012 1016 $context = \sanitize_text_field( \wp_unslash( $_POST['context'] ?? '' ) );
@@ -1014,13 +1018,13 @@
1014 1018 $type = \sanitize_text_field( \wp_unslash( $_POST['type'] ?? '' ) );
1015 1019 $value = \sanitize_text_field( \wp_unslash( $_POST['value'] ?? '' ) );
1016 1020
1017 1021 // Validate required parameters.
1018 - if ( ! \in_array( $context, array( 'user', 'site' ), true ) || ! \in_array( $operation, array( 'add', 'remove' ), true ) ) {
1022 + if ( ! in_array( $context, array( 'user', 'site' ), true ) || ! in_array( $operation, array( 'add', 'remove' ), true ) ) {
1019 1023 \wp_send_json_error( array( 'message' => \__( 'Invalid context or action.', 'activitypub' ) ) );
1020 1024 }
1021 1025
1022 - if ( empty( $type ) || empty( $value ) || ! \in_array( $type, array( 'domain', 'keyword' ), true ) ) {
1026 + if ( empty( $type ) || empty( $value ) || ! in_array( $type, array( 'domain', 'keyword' ), true ) ) {
1023 1027 \wp_send_json_error( array( 'message' => \__( 'Invalid parameters.', 'activitypub' ) ) );
1024 1028 }
1025 1029
1026 1030 // Verify nonce for all operations.
@@ -1063,220 +1067,6 @@
1063 1067 \wp_send_json_success();
1064 1068 } else {
1065 1069 \wp_send_json_error( array( 'message' => $error_message ) );
1066 1070 }
1067 - }
1068 -
1069 - /**
1070 - * AJAX handler for blocklist subscriptions (add/remove).
1071 - */
1072 - public static function ajax_blocklist_subscription() {
1073 - $operation = \sanitize_text_field( \wp_unslash( $_POST['operation'] ?? '' ) );
1074 - $url = \sanitize_url( \wp_unslash( $_POST['url'] ?? '' ) );
1075 -
1076 - // Validate required parameters.
1077 - if ( ! \in_array( $operation, array( 'add', 'remove' ), true ) ) {
1078 - \wp_send_json_error( array( 'message' => \__( 'Invalid operation.', 'activitypub' ) ) );
1079 - }
1080 -
1081 - if ( empty( $url ) ) {
1082 - \wp_send_json_error( array( 'message' => \__( 'Invalid URL.', 'activitypub' ) ) );
1083 - }
1084 -
1085 - // Verify nonce.
1086 - if ( ! \wp_verify_nonce( \sanitize_text_field( \wp_unslash( $_POST['_wpnonce'] ?? '' ) ), 'activitypub_moderation_settings' ) ) {
1087 - \wp_send_json_error( array( 'message' => \__( 'Invalid nonce.', 'activitypub' ) ) );
1088 - }
1089 -
1090 - if ( ! \current_user_can( 'manage_options' ) ) {
1091 - \wp_send_json_error( array( 'message' => \__( 'You do not have permission to perform this action.', 'activitypub' ) ) );
1092 - }
1093 -
1094 - if ( 'add' === $operation ) {
1095 - // First add the subscription (validates URL format).
1096 - if ( ! Blocklist_Subscriptions::add( $url ) ) {
1097 - \wp_send_json_error( array( 'message' => \__( 'Invalid URL.', 'activitypub' ) ) );
1098 - }
1099 -
1100 - // Then sync to validate it works and import domains.
1101 - $result = Blocklist_Subscriptions::sync( $url );
1102 - if ( false === $result ) {
1103 - // Remove the subscription since sync failed.
1104 - Blocklist_Subscriptions::remove( $url );
1105 - \wp_send_json_error( array( 'message' => \__( 'Failed to fetch blocklist. The URL may be unreachable or not contain valid domains.', 'activitypub' ) ) );
1106 - }
1107 -
1108 - \wp_send_json_success();
1109 - } elseif ( Blocklist_Subscriptions::remove( $url ) ) {
1110 - \wp_send_json_success();
1111 - } else {
1112 - \wp_send_json_error( array( 'message' => \__( 'Failed to remove subscription.', 'activitypub' ) ) );
1113 - }
1114 - }
1115 -
1116 - /**
1117 - * AJAX handler for registering a new OAuth client from the user profile.
1118 - *
1119 - * @since 8.1.0
1120 - */
1121 - public static function ajax_register_oauth_client() {
1122 - // Verify nonce.
1123 - if ( ! \wp_verify_nonce( \sanitize_text_field( \wp_unslash( $_POST['_wpnonce'] ?? '' ) ), 'activitypub_connected_apps' ) ) {
1124 - \wp_send_json_error( array( 'message' => \__( 'Invalid nonce.', 'activitypub' ) ) );
1125 - }
1126 -
1127 - if ( ! \current_user_can( 'manage_options' ) ) {
1128 - \wp_send_json_error( array( 'message' => \__( 'You do not have permission to perform this action.', 'activitypub' ) ) );
1129 - }
1130 -
1131 - $name = \sanitize_text_field( \wp_unslash( $_POST['name'] ?? '' ) );
1132 - $redirect_uri = \sanitize_url( \wp_unslash( $_POST['redirect_uri'] ?? '' ) );
1133 -
1134 - if ( empty( $name ) ) {
1135 - \wp_send_json_error( array( 'message' => \__( 'Application name is required.', 'activitypub' ) ) );
1136 - }
1137 -
1138 - if ( empty( $redirect_uri ) ) {
1139 - \wp_send_json_error( array( 'message' => \__( 'Redirect URI is required.', 'activitypub' ) ) );
1140 - }
1141 -
1142 - $result = Client::register(
1143 - array(
1144 - 'name' => $name,
1145 - 'redirect_uris' => array( $redirect_uri ),
1146 - 'is_public' => false,
1147 - )
1148 - );
1149 -
1150 - if ( \is_wp_error( $result ) ) {
1151 - \wp_send_json_error( array( 'message' => $result->get_error_message() ) );
1152 - }
1153 -
1154 - $data = array(
1155 - 'client_id' => $result['client_id'],
1156 - 'created' => \date_i18n( \get_option( 'date_format' ) ),
1157 - );
1158 -
1159 - if ( ! empty( $result['client_secret'] ) ) {
1160 - $data['client_secret'] = $result['client_secret'];
1161 - }
1162 -
1163 - \wp_send_json_success( $data );
1164 - }
1165 -
1166 - /**
1167 - * AJAX handler for deleting a registered OAuth client.
1168 - *
1169 - * @since 8.1.0
1170 - */
1171 - public static function ajax_delete_oauth_client() {
1172 - // Verify nonce.
1173 - if ( ! \wp_verify_nonce( \sanitize_text_field( \wp_unslash( $_POST['_wpnonce'] ?? '' ) ), 'activitypub_connected_apps' ) ) {
1174 - \wp_send_json_error( array( 'message' => \__( 'Invalid nonce.', 'activitypub' ) ) );
1175 - }
1176 -
1177 - if ( ! \current_user_can( 'manage_options' ) ) {
1178 - \wp_send_json_error( array( 'message' => \__( 'You do not have permission to perform this action.', 'activitypub' ) ) );
1179 - }
1180 -
1181 - $client_id = \sanitize_text_field( \wp_unslash( $_POST['client_id'] ?? '' ) );
1182 -
1183 - if ( empty( $client_id ) ) {
1184 - \wp_send_json_error( array( 'message' => \__( 'Invalid client ID.', 'activitypub' ) ) );
1185 - }
1186 -
1187 - $deleted = Client::delete( $client_id );
1188 -
1189 - if ( ! $deleted ) {
1190 - \wp_send_json_error( array( 'message' => \__( 'Failed to delete application.', 'activitypub' ) ) );
1191 - }
1192 -
1193 - \wp_send_json_success( array( 'deleted' => true ) );
1194 - }
1195 -
1196 - /**
1197 - * AJAX handler for deleting all manually registered OAuth clients.
1198 - *
1199 - * @since 8.1.0
1200 - */
1201 - public static function ajax_delete_all_oauth_clients() {
1202 - // Verify nonce.
1203 - if ( ! \wp_verify_nonce( \sanitize_text_field( \wp_unslash( $_POST['_wpnonce'] ?? '' ) ), 'activitypub_connected_apps' ) ) {
1204 - \wp_send_json_error( array( 'message' => \__( 'Invalid nonce.', 'activitypub' ) ) );
1205 - }
1206 -
1207 - if ( ! \current_user_can( 'manage_options' ) ) {
1208 - \wp_send_json_error( array( 'message' => \__( 'You do not have permission to perform this action.', 'activitypub' ) ) );
1209 - }
1210 -
1211 - $clients = Client::get_manually_registered();
1212 -
1213 - foreach ( $clients as $client ) {
1214 - Client::delete( $client->get_client_id() );
1215 - }
1216 -
1217 - \wp_send_json_success( array( 'deleted' => ! empty( $clients ) ) );
1218 - }
1219 -
1220 - /**
1221 - * AJAX handler for revoking an OAuth token from the user profile.
1222 - *
1223 - * Follows the WordPress core Application Passwords pattern.
1224 - *
1225 - * @since 8.1.0
1226 - */
1227 - public static function ajax_revoke_oauth_token() {
1228 - // Verify nonce.
1229 - if ( ! \wp_verify_nonce( \sanitize_text_field( \wp_unslash( $_POST['_wpnonce'] ?? '' ) ), 'activitypub_connected_apps' ) ) {
1230 - \wp_send_json_error( array( 'message' => \__( 'Invalid nonce.', 'activitypub' ) ) );
1231 - }
1232 -
1233 - if ( ! \current_user_can( 'read' ) ) {
1234 - \wp_send_json_error( array( 'message' => \__( 'You do not have permission to perform this action.', 'activitypub' ) ) );
1235 - }
1236 -
1237 - $meta_key = \sanitize_text_field( \wp_unslash( $_POST['meta_key'] ?? '' ) ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Not a DB query parameter.
1238 -
1239 - // Verify the meta key belongs to our token prefix.
1240 - if ( 0 !== \strpos( $meta_key, Token::META_PREFIX ) ) {
1241 - \wp_send_json_error( array( 'message' => \__( 'Invalid token.', 'activitypub' ) ) );
1242 - }
1243 -
1244 - $user_id = \get_current_user_id();
1245 - $token_data = \get_user_meta( $user_id, $meta_key, true );
1246 -
1247 - // Verify the token belongs to the current user.
1248 - if ( empty( $token_data ) || ! \is_array( $token_data ) ) {
1249 - \wp_send_json_error( array( 'message' => \__( 'Token not found.', 'activitypub' ) ) );
1250 - }
1251 -
1252 - // Delete the token.
1253 - \delete_user_meta( $user_id, $meta_key );
1254 -
1255 - // Delete the associated refresh token index.
1256 - if ( ! empty( $token_data['refresh_token_hash'] ) ) {
1257 - \delete_user_meta( $user_id, Token::REFRESH_INDEX_PREFIX . $token_data['refresh_token_hash'] );
1258 - }
1259 -
1260 - \wp_send_json_success( array( 'deleted' => true ) );
1261 - }
1262 -
1263 - /**
1264 - * AJAX handler for revoking all OAuth tokens for the current user.
1265 - *
1266 - * @since 8.1.0
1267 - */
1268 - public static function ajax_revoke_all_oauth_tokens() {
1269 - // Verify nonce.
1270 - if ( ! \wp_verify_nonce( \sanitize_text_field( \wp_unslash( $_POST['_wpnonce'] ?? '' ) ), 'activitypub_connected_apps' ) ) {
1271 - \wp_send_json_error( array( 'message' => \__( 'Invalid nonce.', 'activitypub' ) ) );
1272 - }
1273 -
1274 - if ( ! \current_user_can( 'read' ) ) {
1275 - \wp_send_json_error( array( 'message' => \__( 'You do not have permission to perform this action.', 'activitypub' ) ) );
1276 - }
1277 -
1278 - $count = Token::revoke_all_for_user( \get_current_user_id() );
1279 -
1280 - \wp_send_json_success( array( 'deleted' => $count > 0 ) );
1281 1071 }
1282 1072 }