PluginProbe
ActivityPub / 4.6.0
ActivityPub v4.6.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
activitypub / includes / class-admin.php

class-admin.php in ActivityPub 4.6.0, at includes/class-admin.php

896 lines 25.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin Class.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub;
9
10 use WP_User_Query;
11 use Activitypub\Model\Blog;
12 use Activitypub\Collection\Actors;
13 use Activitypub\Collection\Extra_Fields;
14
15 /**
16 * ActivityPub Admin Class.
17 *
18 * @author Matthias Pfefferle
19 */
20 class Admin {
21 /**
22 * Initialize the class, registering WordPress hooks,
23 */
24 public static function init() {
25 \add_action( 'admin_menu', array( self::class, 'admin_menu' ) );
26 \add_action( 'admin_init', array( self::class, 'register_settings' ) );
27 \add_action( 'load-comment.php', array( self::class, 'edit_comment' ) );
28 \add_action( 'load-post.php', array( self::class, 'edit_post' ) );
29 \add_action( 'load-edit.php', array( self::class, 'list_posts' ) );
30 \add_filter( 'page_row_actions', array( self::class, 'row_actions' ), 10, 2 );
31 \add_filter( 'post_row_actions', array( self::class, 'row_actions' ), 10, 2 );
32 \add_action( 'personal_options_update', array( self::class, 'save_user_settings' ) );
33 \add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_scripts' ) );
34 \add_action( 'admin_notices', array( self::class, 'admin_notices' ) );
35
36 \add_filter( 'comment_row_actions', array( self::class, 'comment_row_actions' ), 10, 2 );
37 \add_filter( 'manage_edit-comments_columns', array( static::class, 'manage_comment_columns' ) );
38 \add_action( 'manage_comments_custom_column', array( static::class, 'manage_comments_custom_column' ), 9, 2 );
39 \add_action( 'admin_comment_types_dropdown', array( static::class, 'comment_types_dropdown' ) );
40
41 \add_filter( 'manage_posts_columns', array( static::class, 'manage_post_columns' ), 10, 2 );
42 \add_action( 'manage_posts_custom_column', array( self::class, 'manage_posts_custom_column' ), 10, 2 );
43
44 \add_filter( 'manage_users_columns', array( self::class, 'manage_users_columns' ) );
45 \add_action( 'manage_users_custom_column', array( self::class, 'manage_users_custom_column' ), 10, 3 );
46 \add_filter( 'bulk_actions-users', array( self::class, 'user_bulk_options' ) );
47 \add_filter( 'handle_bulk_actions-users', array( self::class, 'handle_bulk_request' ), 10, 3 );
48
49 if ( ! is_user_disabled( get_current_user_id() ) ) {
50 \add_action( 'show_user_profile', array( self::class, 'add_profile' ) );
51 }
52
53 \add_filter( 'dashboard_glance_items', array( self::class, 'dashboard_glance_items' ) );
54 \add_filter( 'plugin_action_links_' . ACTIVITYPUB_PLUGIN_BASENAME, array( self::class, 'add_plugin_settings_link' ) );
55 }
56
57 /**
58 * Add admin menu entry.
59 */
60 public static function admin_menu() {
61 $settings_page = \add_options_page(
62 'Welcome',
63 'ActivityPub',
64 'manage_options',
65 'activitypub',
66 array( self::class, 'settings_page' )
67 );
68
69 \add_action(
70 'load-' . $settings_page,
71 array( self::class, 'add_settings_help_tab' )
72 );
73
74 // User has to be able to publish posts.
75 if ( ! is_user_disabled( get_current_user_id() ) ) {
76 $followers_list_page = \add_users_page(
77 \__( '⁂ Followers', 'activitypub' ),
78 \__( '⁂ Followers', 'activitypub' ),
79 'activitypub',
80 'activitypub-followers-list',
81 array(
82 self::class,
83 'followers_list_page',
84 )
85 );
86
87 \add_action(
88 'load-' . $followers_list_page,
89 array( self::class, 'add_followers_list_help_tab' )
90 );
91
92 \add_users_page(
93 \__( '⁂ Extra Fields', 'activitypub' ),
94 \__( '⁂ Extra Fields', 'activitypub' ),
95 'activitypub',
96 \esc_url( \admin_url( '/edit.php?post_type=ap_extrafield' ) )
97 );
98 }
99 }
100
101 /**
102 * Display admin menu notices about configuration problems or conflicts.
103 */
104 public static function admin_notices() {
105 $permalink_structure = \get_option( 'permalink_structure' );
106 if ( empty( $permalink_structure ) ) {
107 $admin_notice = sprintf(
108 /* translators: %s: Permalink settings URL. */
109 \__( 'ActivityPub needs SEO-friendly URLs to work properly. Please <a href="%s">update your permalink structure</a> to an option other than Plain.', 'activitypub' ),
110 esc_url( admin_url( 'options-permalink.php' ) )
111 );
112 self::show_admin_notice( $admin_notice, 'error' );
113 }
114
115 $current_screen = get_current_screen();
116 if ( ! $current_screen ) {
117 return;
118 }
119 if ( 'edit' === $current_screen->base && Extra_Fields::is_extra_fields_post_type( $current_screen->post_type ) ) {
120 ?>
121 <div class="notice" style="margin: 0; background: none; border: none; box-shadow: none; padding: 15px 0 0 0; font-size: 14px;">
122 <?php
123 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' );
124 ?>
125 </div>
126 <?php
127 }
128 }
129
130 /**
131 * Display one admin menu notice about configuration problems or conflicts.
132 *
133 * @param string $admin_notice The notice to display.
134 * @param string $level The level of the notice (error, warning, success, info).
135 */
136 private static function show_admin_notice( $admin_notice, $level ) {
137 ?>
138
139 <div class="notice notice-<?php echo esc_attr( $level ); ?>">
140 <p><?php echo wp_kses( $admin_notice, 'data' ); ?></p>
141 </div>
142
143 <?php
144 }
145
146 /**
147 * Load settings page.
148 */
149 public static function settings_page() {
150 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
151 if ( empty( $_GET['tab'] ) ) {
152 $tab = 'welcome';
153 } else {
154 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
155 $tab = sanitize_key( $_GET['tab'] );
156 }
157
158 switch ( $tab ) {
159 case 'settings':
160 \load_template( ACTIVITYPUB_PLUGIN_DIR . 'templates/settings.php' );
161 break;
162 case 'blog-profile':
163 wp_enqueue_media();
164 wp_enqueue_script( 'activitypub-header-image' );
165
166 \load_template( ACTIVITYPUB_PLUGIN_DIR . 'templates/blog-settings.php' );
167 break;
168 case 'followers':
169 \load_template( ACTIVITYPUB_PLUGIN_DIR . 'templates/blog-followers-list.php' );
170 break;
171 case 'welcome':
172 default:
173 wp_enqueue_script( 'plugin-install' );
174 add_thickbox();
175 wp_enqueue_script( 'updates' );
176
177 \load_template( ACTIVITYPUB_PLUGIN_DIR . 'templates/welcome.php' );
178 break;
179 }
180 }
181
182 /**
183 * Load user settings page
184 */
185 public static function followers_list_page() {
186 // User has to be able to publish posts.
187 if ( ! is_user_disabled( get_current_user_id() ) ) {
188 \load_template( ACTIVITYPUB_PLUGIN_DIR . 'templates/user-followers-list.php' );
189 }
190 }
191
192 /**
193 * Register ActivityPub settings
194 */
195 public static function register_settings() {
196 \register_setting(
197 'activitypub',
198 'activitypub_post_content_type',
199 array(
200 'type' => 'string',
201 'description' => \__( 'Use title and link, summary, full or custom content', 'activitypub' ),
202 'show_in_rest' => array(
203 'schema' => array(
204 'enum' => array(
205 'title',
206 'excerpt',
207 'content',
208 ),
209 ),
210 ),
211 'default' => 'content',
212 )
213 );
214 \register_setting(
215 'activitypub',
216 'activitypub_custom_post_content',
217 array(
218 'type' => 'string',
219 'description' => \__( 'Define your own custom post template', 'activitypub' ),
220 'show_in_rest' => true,
221 'default' => ACTIVITYPUB_CUSTOM_POST_CONTENT,
222 )
223 );
224 \register_setting(
225 'activitypub',
226 'activitypub_max_image_attachments',
227 array(
228 'type' => 'integer',
229 'description' => \__( 'Number of images to attach to posts.', 'activitypub' ),
230 'default' => ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS,
231 )
232 );
233 \register_setting(
234 'activitypub',
235 'activitypub_object_type',
236 array(
237 'type' => 'string',
238 'description' => \__( 'The Activity-Object-Type', 'activitypub' ),
239 'show_in_rest' => array(
240 'schema' => array(
241 'enum' => array(
242 'note',
243 'wordpress-post-format',
244 ),
245 ),
246 ),
247 'default' => ACTIVITYPUB_DEFAULT_OBJECT_TYPE,
248 )
249 );
250 \register_setting(
251 'activitypub',
252 'activitypub_use_hashtags',
253 array(
254 'type' => 'boolean',
255 'description' => \__( 'Add hashtags in the content as native tags and replace the #tag with the tag-link', 'activitypub' ),
256 'default' => '0',
257 )
258 );
259 \register_setting(
260 'activitypub',
261 'activitypub_use_opengraph',
262 array(
263 'type' => 'boolean',
264 'description' => \__( 'Automatically add "fediverse:creator" OpenGraph tags for Authors and the Blog-User.', 'activitypub' ),
265 'default' => '1',
266 )
267 );
268 \register_setting(
269 'activitypub',
270 'activitypub_support_post_types',
271 array(
272 'type' => 'string',
273 'description' => \esc_html__( 'Enable ActivityPub support for post types', 'activitypub' ),
274 'show_in_rest' => true,
275 'default' => array( 'post' ),
276 )
277 );
278 \register_setting(
279 'activitypub',
280 'activitypub_actor_mode',
281 array(
282 'type' => 'integer',
283 'description' => \__( 'Choose your preferred Actor-Mode.', 'activitypub' ),
284 'default' => ACTIVITYPUB_ACTOR_MODE,
285 )
286 );
287
288 \register_setting(
289 'activitypub',
290 'activitypub_attribution_domains',
291 array(
292 'type' => 'string',
293 'description' => \__( 'Websites allowed to credit you.', 'activitypub' ),
294 'default' => home_host(),
295 'sanitize_callback' => function ( $value ) {
296 $value = explode( PHP_EOL, $value );
297 $value = array_filter( array_map( 'trim', $value ) );
298 $value = array_filter( array_map( 'esc_attr', $value ) );
299 $value = implode( PHP_EOL, $value );
300
301 return $value;
302 },
303 )
304 );
305
306 \register_setting(
307 'activitypub',
308 'activitypub_authorized_fetch',
309 array(
310 'type' => 'boolean',
311 'description' => \__( 'Require HTTP signature authentication.', 'activitypub' ),
312 'default' => false,
313 )
314 );
315
316 \register_setting(
317 'activitypub',
318 'activitypub_mailer_new_follower',
319 array(
320 'type' => 'boolean',
321 'description' => \__( 'Send notifications via e-mail when a new follower is added.', 'activitypub' ),
322 'default' => '0',
323 )
324 );
325 \register_setting(
326 'activitypub',
327 'activitypub_mailer_new_dm',
328 array(
329 'type' => 'boolean',
330 'description' => \__( 'Send notifications via e-mail when a direct message is received.', 'activitypub' ),
331 'default' => '0',
332 )
333 );
334
335 // Blog-User Settings.
336 \register_setting(
337 'activitypub_blog',
338 'activitypub_blog_description',
339 array(
340 'type' => 'string',
341 'description' => \esc_html__( 'The Description of the Blog-User', 'activitypub' ),
342 'show_in_rest' => true,
343 'default' => '',
344 )
345 );
346 \register_setting(
347 'activitypub_blog',
348 'activitypub_blog_identifier',
349 array(
350 'type' => 'string',
351 'description' => \esc_html__( 'The Identifier of the Blog-User', 'activitypub' ),
352 'show_in_rest' => true,
353 'default' => Blog::get_default_username(),
354 'sanitize_callback' => function ( $value ) {
355 // Hack to allow dots in the username.
356 $parts = explode( '.', $value );
357 $sanitized = array();
358
359 foreach ( $parts as $part ) {
360 $sanitized[] = \sanitize_title( $part );
361 }
362
363 $sanitized = implode( '.', $sanitized );
364
365 // Check for login or nicename.
366 $user = new WP_User_Query(
367 array(
368 'search' => $sanitized,
369 'search_columns' => array( 'user_login', 'user_nicename' ),
370 'number' => 1,
371 'hide_empty' => true,
372 'fields' => 'ID',
373 )
374 );
375
376 if ( $user->results ) {
377 add_settings_error(
378 'activitypub_blog_identifier',
379 'activitypub_blog_identifier',
380 \esc_html__( 'You cannot use an existing author\'s name for the blog profile ID.', 'activitypub' ),
381 'error'
382 );
383
384 return Blog::get_default_username();
385 }
386
387 return $sanitized;
388 },
389 )
390 );
391 \register_setting(
392 'activitypub_blog',
393 'activitypub_header_image',
394 array(
395 'type' => 'integer',
396 'description' => \__( 'The Attachment-ID of the Sites Header-Image', 'activitypub' ),
397 'default' => null,
398 )
399 );
400 }
401
402 /**
403 * Adds the ActivityPub settings to the Help tab.
404 */
405 public static function add_settings_help_tab() {
406 require_once ACTIVITYPUB_PLUGIN_DIR . 'includes/help.php';
407 }
408
409 /**
410 * Adds the follower list to the Help tab.
411 */
412 public static function add_followers_list_help_tab() {
413 // todo.
414 }
415
416 /**
417 * Add the profile.
418 *
419 * @param \WP_User $user The user object.
420 */
421 public static function add_profile( $user ) {
422 $description = \get_user_option( 'activitypub_description', $user->ID );
423
424 wp_enqueue_media();
425 wp_enqueue_script( 'activitypub-header-image' );
426
427 \load_template(
428 ACTIVITYPUB_PLUGIN_DIR . 'templates/user-settings.php',
429 true,
430 array(
431 'description' => $description,
432 )
433 );
434 }
435
436 /**
437 * Save the user settings.
438 *
439 * Handles the saving of the ActivityPub settings.
440 *
441 * @param int $user_id The user ID.
442 */
443 public static function save_user_settings( $user_id ) {
444 if ( ! isset( $_REQUEST['_apnonce'] ) ) {
445 return;
446 }
447
448 $nonce = sanitize_text_field( wp_unslash( $_REQUEST['_apnonce'] ) );
449 if (
450 ! wp_verify_nonce( $nonce, 'activitypub-user-settings' ) ||
451 ! current_user_can( 'edit_user', $user_id )
452 ) {
453 return;
454 }
455
456 $description = ! empty( $_POST['activitypub_description'] ) ? sanitize_textarea_field( wp_unslash( $_POST['activitypub_description'] ) ) : false;
457 if ( $description ) {
458 \update_user_option( $user_id, 'activitypub_description', $description );
459 } else {
460 \delete_user_option( $user_id, 'activitypub_description' );
461 }
462
463 $header_image = ! empty( $_POST['activitypub_header_image'] ) ? sanitize_text_field( wp_unslash( $_POST['activitypub_header_image'] ) ) : false;
464 if ( $header_image && \wp_attachment_is_image( $header_image ) ) {
465 \update_user_option( $user_id, 'activitypub_header_image', $header_image );
466 } else {
467 \delete_user_option( $user_id, 'activitypub_header_image' );
468 }
469 }
470
471 /**
472 * Enqueue the admin scripts and styles.
473 *
474 * @param string $hook_suffix The current page.
475 */
476 public static function enqueue_scripts( $hook_suffix ) {
477 wp_register_script(
478 'activitypub-header-image',
479 plugins_url(
480 'assets/js/activitypub-header-image.js',
481 ACTIVITYPUB_PLUGIN_FILE
482 ),
483 array( 'jquery' ),
484 ACTIVITYPUB_PLUGIN_VERSION,
485 false
486 );
487
488 if ( false !== strpos( $hook_suffix, 'activitypub' ) ) {
489 wp_enqueue_style(
490 'activitypub-admin-styles',
491 plugins_url(
492 'assets/css/activitypub-admin.css',
493 ACTIVITYPUB_PLUGIN_FILE
494 ),
495 array(),
496 ACTIVITYPUB_PLUGIN_VERSION
497 );
498 wp_enqueue_script(
499 'activitypub-admin-script',
500 plugins_url(
501 'assets/js/activitypub-admin.js',
502 ACTIVITYPUB_PLUGIN_FILE
503 ),
504 array( 'jquery' ),
505 ACTIVITYPUB_PLUGIN_VERSION,
506 false
507 );
508 }
509
510 if ( 'index.php' === $hook_suffix ) {
511 wp_enqueue_style(
512 'activitypub-admin-styles',
513 plugins_url(
514 'assets/css/activitypub-admin.css',
515 ACTIVITYPUB_PLUGIN_FILE
516 ),
517 array(),
518 ACTIVITYPUB_PLUGIN_VERSION
519 );
520 }
521 }
522
523 /**
524 * Hook into the edit_comment functionality.
525 *
526 * Disables the edit_comment capability for federated comments.
527 */
528 public static function edit_comment() {
529 // Disable the edit_comment capability for federated comments.
530 \add_filter(
531 'user_has_cap',
532 function ( $allcaps, $caps, $arg ) {
533 if ( 'edit_comment' !== $arg[0] ) {
534 return $allcaps;
535 }
536
537 if ( was_comment_received( $arg[2] ) ) {
538 return false;
539 }
540
541 return $allcaps;
542 },
543 1,
544 3
545 );
546 }
547
548 /**
549 * Hook into the edit_post functionality.
550 *
551 * Disables the edit_post capability for federated posts.
552 */
553 public static function edit_post() {
554 // Disable the edit_post capability for federated posts.
555 \add_filter(
556 'user_has_cap',
557 function ( $allcaps, $caps, $arg ) {
558 if ( 'edit_post' !== $arg[0] ) {
559 return $allcaps;
560 }
561
562 $post = get_post( $arg[2] );
563
564 if ( ! Extra_Fields::is_extra_field_post_type( $post->post_type ) ) {
565 return $allcaps;
566 }
567
568 if ( (int) get_current_user_id() !== (int) $post->post_author ) {
569 return false;
570 }
571
572 return $allcaps;
573 },
574 1,
575 3
576 );
577 }
578
579 /**
580 * Add ActivityPub specific actions/filters to the post list view.
581 */
582 public static function list_posts() {
583 // Show only the user's extra fields.
584 \add_action(
585 'pre_get_posts',
586 function ( $query ) {
587 if ( $query->get( 'post_type' ) === 'ap_extrafield' ) {
588 $query->set( 'author', get_current_user_id() );
589 }
590 }
591 );
592
593 // Remove all views for the extra fields.
594 $screen_id = get_current_screen()->id;
595
596 add_filter(
597 "views_{$screen_id}",
598 function ( $views ) {
599 if ( Extra_Fields::is_extra_fields_post_type( get_current_screen()->post_type ) ) {
600 return array();
601 }
602
603 return $views;
604 }
605 );
606 }
607
608 /**
609 * Comment row actions.
610 *
611 * @param array $actions The existing actions.
612 * @param int|\WP_Comment $comment The comment object or ID.
613 *
614 * @return array The modified actions.
615 */
616 public static function comment_row_actions( $actions, $comment ) {
617 if ( was_comment_received( $comment ) ) {
618 unset( $actions['edit'] );
619 unset( $actions['quickedit'] );
620 }
621
622 if ( in_array( get_comment_type( $comment ), Comment::get_comment_type_slugs(), true ) ) {
623 unset( $actions['reply'] );
624 }
625
626 return $actions;
627 }
628
629 /**
630 * Add a column "activitypub".
631 *
632 * This column shows if the user has the capability to use ActivityPub.
633 *
634 * @param array $columns The columns.
635 *
636 * @return array The columns extended by the activitypub.
637 */
638 public static function manage_users_columns( $columns ) {
639 $columns['activitypub'] = __( 'ActivityPub', 'activitypub' );
640 return $columns;
641 }
642
643 /**
644 * Add "comment-type" and "protocol" as column in WP-Admin.
645 *
646 * @param array $columns The list of column names.
647 *
648 * @return array The extended list of column names.
649 */
650 public static function manage_comment_columns( $columns ) {
651 $columns['comment_type'] = esc_attr__( 'Comment-Type', 'activitypub' );
652 $columns['comment_protocol'] = esc_attr__( 'Protocol', 'activitypub' );
653
654 return $columns;
655 }
656
657 /**
658 * Add "post_content" as column for Extra-Fields in WP-Admin.
659 *
660 * @param array $columns The list of column names.
661 * @param string $post_type The post type.
662 *
663 * @return array The extended list of column names.
664 */
665 public static function manage_post_columns( $columns, $post_type ) {
666 if ( Extra_Fields::is_extra_fields_post_type( $post_type ) ) {
667 $after_key = 'title';
668 $index = array_search( $after_key, array_keys( $columns ), true );
669 $columns = array_slice( $columns, 0, $index + 1 ) + array( 'extra_field_content' => esc_attr__( 'Content', 'activitypub' ) ) + $columns;
670 }
671
672 return $columns;
673 }
674
675 /**
676 * Add "comment-type" and "protocol" as column in WP-Admin.
677 *
678 * @param array $column The column to implement.
679 * @param int $comment_id The comment id.
680 */
681 public static function manage_comments_custom_column( $column, $comment_id ) {
682 if ( 'comment_type' === $column && ! defined( 'WEBMENTION_PLUGIN_DIR' ) ) {
683 echo esc_attr( ucfirst( get_comment_type( $comment_id ) ) );
684 } elseif ( 'comment_protocol' === $column ) {
685 $protocol = get_comment_meta( $comment_id, 'protocol', true );
686
687 if ( $protocol ) {
688 echo esc_attr( ucfirst( str_replace( 'activitypub', 'ActivityPub', $protocol ) ) );
689 } else {
690 esc_attr_e( 'Local', 'activitypub' );
691 }
692 }
693 }
694
695 /**
696 * Add the new ActivityPub comment types to the comment types dropdown.
697 *
698 * @param array $types The existing comment types.
699 *
700 * @return array The extended comment types.
701 */
702 public static function comment_types_dropdown( $types ) {
703 foreach ( Comment::get_comment_types() as $comment_type ) {
704 $types[ $comment_type['type'] ] = esc_html( $comment_type['label'] );
705 }
706
707 return $types;
708 }
709
710 /**
711 * Return the results for the activitypub column.
712 *
713 * @param string $output Custom column output. Default empty.
714 * @param string $column_name Column name.
715 * @param int $user_id ID of the currently-listed user.
716 *
717 * @return string The column contents.
718 */
719 public static function manage_users_custom_column( $output, $column_name, $user_id ) {
720 if ( 'activitypub' !== $column_name ) {
721 return $output;
722 }
723
724 if ( \user_can( $user_id, 'activitypub' ) ) {
725 return '<span aria-hidden="true">&#x2713;</span><span class="screen-reader-text">' . esc_html__( 'ActivityPub enabled for this author', 'activitypub' ) . '</span>';
726 } else {
727 return '<span aria-hidden="true">&#x2717;</span><span class="screen-reader-text">' . esc_html__( 'ActivityPub disabled for this author', 'activitypub' ) . '</span>';
728 }
729 }
730
731 /**
732 * Add a column "extra_field_content" to the post list view.
733 *
734 * @param string $column_name The column name.
735 * @param int $post_id The post ID.
736 *
737 * @return void
738 */
739 public static function manage_posts_custom_column( $column_name, $post_id ) {
740 if ( 'extra_field_content' === $column_name ) {
741 $post = get_post( $post_id );
742 if ( Extra_Fields::is_extra_fields_post_type( $post->post_type ) ) {
743 echo esc_attr( wp_strip_all_tags( $post->post_content ) );
744 }
745 }
746 }
747
748 /**
749 * Add options to the Bulk dropdown on the users page.
750 *
751 * @param array $actions The existing bulk options.
752 *
753 * @return array The extended bulk options.
754 */
755 public static function user_bulk_options( $actions ) {
756 $actions['add_activitypub_cap'] = __( 'Enable for ActivityPub', 'activitypub' );
757 $actions['remove_activitypub_cap'] = __( 'Disable for ActivityPub', 'activitypub' );
758
759 return $actions;
760 }
761
762 /**
763 * Handle bulk activitypub requests.
764 *
765 * * `add_activitypub_cap` - Add the activitypub capability to the selected users.
766 * * `remove_activitypub_cap` - Remove the activitypub capability from the selected users.
767 *
768 * @param string $sendback The URL to send the user back to.
769 * @param string $action The requested action.
770 * @param array $users The selected users.
771 *
772 * @return string The URL to send the user back to.
773 */
774 public static function handle_bulk_request( $sendback, $action, $users ) {
775 if (
776 'remove_activitypub_cap' !== $action &&
777 'add_activitypub_cap' !== $action
778 ) {
779 return $sendback;
780 }
781
782 foreach ( $users as $user_id ) {
783 $user = new \WP_User( $user_id );
784 if (
785 'add_activitypub_cap' === $action &&
786 user_can( $user_id, 'publish_posts' )
787 ) {
788 $user->add_cap( 'activitypub' );
789 } elseif ( 'remove_activitypub_cap' === $action ) {
790 $user->remove_cap( 'activitypub' );
791 }
792 }
793
794 return $sendback;
795 }
796
797 /**
798 * Add ActivityPub infos to the dashboard glance items.
799 *
800 * @param array $items The existing glance items.
801 *
802 * @return array The extended glance items.
803 */
804 public static function dashboard_glance_items( $items ) {
805 \add_filter( 'number_format_i18n', '\Activitypub\custom_large_numbers', 10, 3 );
806
807 if ( ! is_user_disabled( get_current_user_id() ) ) {
808 $follower_count = sprintf(
809 // translators: %s: number of followers.
810 _n(
811 '%s Follower',
812 '%s Followers',
813 count_followers( \get_current_user_id() ),
814 'activitypub'
815 ),
816 \number_format_i18n( count_followers( \get_current_user_id() ) )
817 );
818 $items['activitypub-followers-user'] = sprintf(
819 '<a class="activitypub-followers" href="%1$s" title="%2$s">%3$s</a>',
820 \esc_url( \admin_url( 'users.php?page=activitypub-followers-list' ) ),
821 \esc_attr__( 'Your followers', 'activitypub' ),
822 \esc_html( $follower_count )
823 );
824 }
825
826 if ( ! is_user_type_disabled( 'blog' ) && current_user_can( 'manage_options' ) ) {
827 $follower_count = sprintf(
828 // translators: %s: number of followers.
829 _n(
830 '%s Follower (Blog)',
831 '%s Followers (Blog)',
832 count_followers( Actors::BLOG_USER_ID ),
833 'activitypub'
834 ),
835 \number_format_i18n( count_followers( Actors::BLOG_USER_ID ) )
836 );
837 $items['activitypub-followers-blog'] = sprintf(
838 '<a class="activitypub-followers" href="%1$s" title="%2$s">%3$s</a>',
839 \esc_url( \admin_url( 'options-general.php?page=activitypub&tab=followers' ) ),
840 \esc_attr__( 'The Blog\'s followers', 'activitypub' ),
841 \esc_html( $follower_count )
842 );
843 }
844
845 \remove_filter( 'number_format_i18n', '\Activitypub\custom_large_numbers' );
846
847 return $items;
848 }
849
850 /**
851 * Add a "⁂ Preview" link to the row actions.
852 *
853 * @param array $actions The existing actions.
854 * @param \WP_Post $post The post object.
855 *
856 * @return array The modified actions.
857 */
858 public static function row_actions( $actions, $post ) {
859 // check if the post is enabled for ActivityPub.
860 if (
861 ! \post_type_supports( \get_post_type( $post ), 'activitypub' ) ||
862 ! in_array( $post->post_status, array( 'pending', 'draft', 'future', 'publish' ), true ) ||
863 ! \current_user_can( 'edit_post', $post->ID ) ||
864 ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL === get_content_visibility( $post ) ||
865 site_supports_blocks()
866 ) {
867 return $actions;
868 }
869
870 $preview_url = add_query_arg( 'activitypub', 'true', \get_preview_post_link( $post ) );
871
872 $actions['activitypub'] = sprintf(
873 '<a href="%s" target="_blank">%s</a>',
874 \esc_url( $preview_url ),
875 \esc_html__( '⁂ Fediverse Preview', 'activitypub' )
876 );
877
878 return $actions;
879 }
880
881 /**
882 * Add plugin settings link.
883 *
884 * @param array $actions The current actions.
885 */
886 public static function add_plugin_settings_link( $actions ) {
887 $actions[] = \sprintf(
888 '<a href="%1s">%2s</a>',
889 \menu_page_url( 'activitypub', false ),
890 \__( 'Settings', 'activitypub' )
891 );
892
893 return $actions;
894 }
895 }
896