PluginProbe
ActivityPub / 4.3.0
ActivityPub v4.3.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.3.0, at includes/class-admin.php

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