PluginProbe
ActivityPub / 7.0.0
ActivityPub v7.0.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 / wp-admin / class-settings.php

class-settings.php in ActivityPub 7.0.0, at includes/wp-admin/class-settings.php

769 lines 24.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Settings file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub\WP_Admin;
9
10 use Activitypub\Collection\Actors;
11 use Activitypub\Model\Blog;
12 use Activitypub\Sanitize;
13 use function Activitypub\user_can_activitypub;
14
15 /**
16 * ActivityPub Settings Class.
17 */
18 class Settings {
19 /**
20 * Initialize the class, registering WordPress hooks,
21 */
22 public static function init() {
23 \add_action( 'admin_init', array( self::class, 'register_settings' ), 11 );
24 \add_action( 'admin_menu', array( self::class, 'add_settings_page' ) );
25
26 \add_action( 'load-settings_page_activitypub', array( self::class, 'handle_welcome_query_arg' ) );
27 \add_filter( 'screen_settings', array( self::class, 'add_screen_option' ), 10, 2 );
28 \add_filter( 'screen_options_show_submit', array( self::class, 'screen_options_show_submit' ), 10, 2 );
29 }
30
31 /**
32 * Register ActivityPub settings
33 */
34 public static function register_settings() {
35 \register_setting(
36 'activitypub',
37 'activitypub_post_content_type',
38 array(
39 'type' => 'string',
40 'description' => \__( 'Use title and link, summary, full or custom content', 'activitypub' ),
41 'show_in_rest' => array(
42 'schema' => array(
43 'enum' => array( 'title', 'excerpt', 'content' ),
44 ),
45 ),
46 'default' => 'content',
47 )
48 );
49
50 \register_setting(
51 'activitypub',
52 'activitypub_custom_post_content',
53 array(
54 'type' => 'string',
55 'description' => \__( 'Define your own custom post template', 'activitypub' ),
56 'show_in_rest' => true,
57 'default' => ACTIVITYPUB_CUSTOM_POST_CONTENT,
58 )
59 );
60
61 \register_setting(
62 'activitypub',
63 'activitypub_max_image_attachments',
64 array(
65 'type' => 'integer',
66 'description' => \__( 'Number of images to attach to posts.', 'activitypub' ),
67 'default' => ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS,
68 'sanitize_callback' => function ( $value ) {
69 return \is_numeric( $value ) ? \absint( $value ) : ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS;
70 },
71 )
72 );
73
74 \register_setting(
75 'activitypub',
76 'activitypub_object_type',
77 array(
78 'type' => 'string',
79 'description' => \__( 'The Activity-Object-Type', 'activitypub' ),
80 'show_in_rest' => array(
81 'schema' => array(
82 'enum' => array( 'note', 'wordpress-post-format' ),
83 ),
84 ),
85 'default' => ACTIVITYPUB_DEFAULT_OBJECT_TYPE,
86 )
87 );
88
89 \register_setting(
90 'activitypub',
91 'activitypub_use_hashtags',
92 array(
93 'type' => 'boolean',
94 'description' => \__( 'Add hashtags in the content as native tags and replace the #tag with the tag-link', 'activitypub' ),
95 'default' => '0',
96 )
97 );
98
99 \register_setting(
100 'activitypub',
101 'activitypub_use_opengraph',
102 array(
103 'type' => 'boolean',
104 'description' => \__( 'Automatically add "fediverse:creator" OpenGraph tags for Authors and the Blog-User.', 'activitypub' ),
105 'default' => '1',
106 )
107 );
108
109 \register_setting(
110 'activitypub',
111 'activitypub_support_post_types',
112 array(
113 'type' => 'string',
114 'description' => \esc_html__( 'Enable ActivityPub support for post types', 'activitypub' ),
115 'show_in_rest' => true,
116 'default' => array( 'post' ),
117 )
118 );
119
120 \register_setting(
121 'activitypub',
122 'activitypub_actor_mode',
123 array(
124 'type' => 'integer',
125 'description' => \__( 'Choose your preferred Actor-Mode.', 'activitypub' ),
126 'default' => ACTIVITYPUB_ACTOR_MODE,
127 )
128 );
129
130 \register_setting(
131 'activitypub',
132 'activitypub_attribution_domains',
133 array(
134 'type' => 'string',
135 'description' => \__( 'Websites allowed to credit you.', 'activitypub' ),
136 'default' => \Activitypub\home_host(),
137 'sanitize_callback' => array( Sanitize::class, 'host_list' ),
138 )
139 );
140
141 \register_setting(
142 'activitypub',
143 'activitypub_allow_likes',
144 array(
145 'type' => 'integer',
146 'description' => \__( 'Allow likes.', 'activitypub' ),
147 'default' => '1',
148 'sanitize_callback' => 'absint',
149 )
150 );
151
152 \register_setting(
153 'activitypub',
154 'activitypub_allow_reposts',
155 array(
156 'type' => 'integer',
157 'description' => \__( 'Allow reposts.', 'activitypub' ),
158 'default' => '1',
159 'sanitize_callback' => 'absint',
160 )
161 );
162
163 \register_setting(
164 'activitypub',
165 'activitypub_auto_approve_reactions',
166 array(
167 'type' => 'integer',
168 'description' => \__( 'Auto approve Reactions.', 'activitypub' ),
169 'default' => '0',
170 'sanitize_callback' => 'absint',
171 )
172 );
173
174 \register_setting(
175 'activitypub',
176 'activitypub_relays',
177 array(
178 'type' => 'array',
179 'description' => \__( 'Relays', 'activitypub' ),
180 'default' => array(),
181 'sanitize_callback' => array( Sanitize::class, 'url_list' ),
182 )
183 );
184
185 \register_setting(
186 'activitypub_advanced',
187 'activitypub_outbox_purge_days',
188 array(
189 'type' => 'integer',
190 'description' => \__( 'Number of days to keep items in the Outbox.', 'activitypub' ),
191 'default' => 180,
192 )
193 );
194
195 \register_setting(
196 'activitypub_advanced',
197 'activitypub_vary_header',
198 array(
199 'type' => 'boolean',
200 'description' => \__( 'Add the Vary header to the ActivityPub response.', 'activitypub' ),
201 'default' => true,
202 )
203 );
204
205 \register_setting(
206 'activitypub_advanced',
207 'activitypub_content_negotiation',
208 array(
209 'type' => 'boolean',
210 'description' => 'Enable content negotiation.',
211 'default' => true,
212 )
213 );
214
215 \register_setting(
216 'activitypub_advanced',
217 'activitypub_authorized_fetch',
218 array(
219 'type' => 'boolean',
220 'description' => \__( 'Require HTTP signature authentication.', 'activitypub' ),
221 'default' => false,
222 )
223 );
224
225 \register_setting(
226 'activitypub_advanced',
227 'activitypub_rfc9421_signature',
228 array(
229 'type' => 'boolean',
230 'description' => 'Use RFC-9421 signature.',
231 'default' => false,
232 )
233 );
234
235 \register_setting(
236 'activitypub_advanced',
237 'activitypub_shared_inbox',
238 array(
239 'type' => 'boolean',
240 'description' => \__( 'Enable the shared inbox.', 'activitypub' ),
241 'default' => false,
242 )
243 );
244
245 // Blog-User Settings.
246 \register_setting(
247 'activitypub_blog',
248 'activitypub_blog_description',
249 array(
250 'type' => 'string',
251 'description' => \esc_html__( 'The Description of the Blog-User', 'activitypub' ),
252 'show_in_rest' => true,
253 'default' => '',
254 )
255 );
256
257 \register_setting(
258 'activitypub_blog',
259 'activitypub_blog_identifier',
260 array(
261 'type' => 'string',
262 'description' => \esc_html__( 'The Identifier of the Blog-User', 'activitypub' ),
263 'show_in_rest' => true,
264 'default' => Blog::get_default_username(),
265 'sanitize_callback' => array( Sanitize::class, 'blog_identifier' ),
266 )
267 );
268
269 \register_setting(
270 'activitypub_blog',
271 'activitypub_header_image',
272 array(
273 'type' => 'integer',
274 'description' => \__( 'The Attachment-ID of the Sites Header-Image', 'activitypub' ),
275 'default' => null,
276 )
277 );
278
279 \register_setting(
280 'activitypub_blog',
281 'activitypub_blog_user_mailer_new_dm',
282 array(
283 'type' => 'integer',
284 'description' => 'Send a notification when someone sends a user of the blog a direct message.',
285 'default' => 1,
286 )
287 );
288
289 \register_setting(
290 'activitypub_blog',
291 'activitypub_blog_user_mailer_new_follower',
292 array(
293 'type' => 'integer',
294 'description' => 'Send a notification when someone starts to follow a user of the blog.',
295 'default' => 1,
296 )
297 );
298
299 \register_setting(
300 'activitypub_blog',
301 'activitypub_blog_user_mailer_new_mention',
302 array(
303 'type' => 'integer',
304 'description' => 'Send a notification when someone mentions a user of the blog.',
305 'default' => 1,
306 )
307 );
308
309 \register_setting(
310 'activitypub_blog',
311 'activitypub_blog_user_also_known_as',
312 array(
313 'type' => 'array',
314 'description' => 'An array of URLs that the blog user is known by.',
315 'default' => array(),
316 'sanitize_callback' => array( Sanitize::class, 'url_list' ),
317 )
318 );
319 }
320
321 /**
322 * Load settings page.
323 */
324 public static function settings_page() {
325 $show_welcome_tab = \get_user_meta( \get_current_user_id(), 'activitypub_show_welcome_tab', true );
326 $show_advanced_tab = \get_user_meta( \get_current_user_id(), 'activitypub_show_advanced_tab', true );
327 $settings_tabs = array();
328 $settings_tab = array(
329 'label' => __( 'Settings', 'activitypub' ),
330 'template' => ACTIVITYPUB_PLUGIN_DIR . 'templates/settings.php',
331 );
332
333 if ( $show_welcome_tab ) {
334 $settings_tabs['welcome'] = array(
335 'label' => __( 'Welcome', 'activitypub' ),
336 'template' => ACTIVITYPUB_PLUGIN_DIR . 'templates/welcome.php',
337 );
338 }
339
340 $settings_tabs['settings'] = $settings_tab;
341
342 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
343 if ( ( isset( $_GET['tab'] ) && 'advanced' === $_GET['tab'] ) || $show_advanced_tab ) {
344 $settings_tabs['advanced'] = array(
345 'label' => \__( 'Advanced', 'activitypub' ),
346 'template' => ACTIVITYPUB_PLUGIN_DIR . 'templates/advanced-settings.php',
347 );
348 }
349
350 if ( user_can_activitypub( Actors::BLOG_USER_ID ) ) {
351 $settings_tabs['blog-profile'] = array(
352 'label' => __( 'Blog Profile', 'activitypub' ),
353 'template' => ACTIVITYPUB_PLUGIN_DIR . 'templates/blog-settings.php',
354 );
355 $settings_tabs['followers'] = array(
356 'label' => __( 'Followers', 'activitypub' ),
357 'template' => ACTIVITYPUB_PLUGIN_DIR . 'templates/blog-followers-list.php',
358 );
359
360 if ( \apply_filters( 'activitypub_show_following_ui', false ) ) {
361 $settings_tabs['following'] = array(
362 'label' => __( 'Following', 'activitypub' ),
363 'template' => ACTIVITYPUB_PLUGIN_DIR . 'templates/blog-following-list.php',
364 );
365 }
366 }
367
368 /**
369 * Filters the tabs displayed in the ActivityPub settings.
370 *
371 * @param array $settings_tabs The tabs to display.
372 */
373 $settings_tabs = \apply_filters( 'activitypub_admin_settings_tabs', $settings_tabs );
374
375 if ( empty( $settings_tabs ) ) {
376 _doing_it_wrong( __FUNCTION__, 'No settings tabs found. There should be at least one tab to show a settings page.', 'unreleased' );
377 $settings_tabs['settings'] = $settings_tab;
378 }
379
380 $tab_keys = array_keys( $settings_tabs );
381 $default_tab = reset( $tab_keys );
382 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
383 $tab = isset( $_GET['tab'] ) ? \sanitize_key( $_GET['tab'] ) : $default_tab;
384
385 if ( ! isset( $settings_tabs[ $tab ] ) ) {
386 $tab = $default_tab;
387 }
388
389 switch ( $tab ) {
390 case 'blog-profile':
391 \wp_enqueue_media();
392 \wp_enqueue_script( 'activitypub-header-image' );
393 break;
394 case 'settings':
395 \update_option( 'activitypub_checklist_settings_visited', '1' );
396 break;
397 default:
398 if ( isset( $_GET['help-tab'] ) && 'getting-started' === $_GET['help-tab'] ) { // phpcs:ignore WordPress.Security.NonceVerification
399 \update_option( 'activitypub_checklist_fediverse_intro_visited', '1' );
400 } elseif ( isset( $_GET['help-tab'] ) && 'editor-blocks' === $_GET['help-tab'] ) { // phpcs:ignore WordPress.Security.NonceVerification
401 \update_option( 'activitypub_checklist_blocks_visited', '1' );
402 }
403 break;
404 }
405
406 // Only show tabs if there are more than one.
407 $labels = array();
408 if ( \count( $settings_tabs ) > 1 ) {
409 $labels = \wp_list_pluck( $settings_tabs, 'label' );
410 }
411
412 $args = \array_fill_keys( \array_keys( $labels ), '' );
413 $args[ $tab ] = 'active';
414 $args['tabs'] = $labels;
415
416 \load_template( ACTIVITYPUB_PLUGIN_DIR . 'templates/admin-header.php', true, $args );
417 \load_template( $settings_tabs[ $tab ]['template'] );
418 }
419
420 /**
421 * Adds the ActivityPub settings to the Help tab.
422 */
423 public static function add_settings_help_tab() {
424 // Getting Started / Introduction to the Fediverse.
425 \get_current_screen()->add_help_tab(
426 array(
427 'id' => 'getting-started',
428 'title' => \__( 'Getting Started', 'activitypub' ),
429 'content' => self::get_help_tab_template( 'getting-started' ),
430 )
431 );
432
433 // Core Features.
434 \get_current_screen()->add_help_tab(
435 array(
436 'id' => 'core-features',
437 'title' => \__( 'Core Features', 'activitypub' ),
438 'content' => self::get_help_tab_template( 'core-features' ),
439 )
440 );
441
442 // Editor Blocks.
443 \get_current_screen()->add_help_tab(
444 array(
445 'id' => 'editor-blocks',
446 'title' => \__( 'Editor Blocks', 'activitypub' ),
447 'content' => self::get_help_tab_template( 'editor-blocks' ),
448 )
449 );
450
451 // Account Migration.
452 \get_current_screen()->add_help_tab(
453 array(
454 'id' => 'account-migration',
455 'title' => \__( 'Account Migration', 'activitypub' ),
456 'content' => self::get_help_tab_template( 'account-migration' ),
457 )
458 );
459
460 // Template Tags.
461 \get_current_screen()->add_help_tab(
462 array(
463 'id' => 'template-tags',
464 'title' => \__( 'Template Tags', 'activitypub' ),
465 'content' => self::get_help_tab_template( 'template-tags' ),
466 )
467 );
468
469 // Recommended Plugins.
470 if ( ! empty( self::get_recommended_plugins() ) ) {
471 \get_current_screen()->add_help_tab(
472 array(
473 'id' => 'recommended-plugins',
474 'title' => __( 'Recommended Plugins', 'activitypub' ),
475 'content' =>
476 '<h2>' . esc_html__( 'Supercharge Your Fediverse Experience', 'activitypub' ) . '</h2>' .
477 '<p>' . esc_html__( 'Enhance your WordPress ActivityPub setup with these hand-picked plugins, each adding unique capabilities for a richer Fediverse experience.', 'activitypub' ) . '</p>' .
478 self::render_recommended_plugins_list(),
479 )
480 );
481 }
482
483 // Troubleshooting.
484 \get_current_screen()->add_help_tab(
485 array(
486 'id' => 'troubleshooting',
487 'title' => \__( 'Troubleshooting', 'activitypub' ),
488 'content' => self::get_help_tab_template( 'troubleshooting' ),
489 )
490 );
491
492 // Glossary.
493 \get_current_screen()->add_help_tab(
494 array(
495 'id' => 'glossary',
496 'title' => \__( 'Glossary', 'activitypub' ),
497 'content' => self::get_help_tab_template( 'glossary' ),
498 )
499 );
500
501 // Resources.
502 \get_current_screen()->add_help_tab(
503 array(
504 'id' => 'resources',
505 'title' => \__( 'Resources', 'activitypub' ),
506 'content' => self::get_help_tab_template( 'resources' ),
507 )
508 );
509
510 // Enhanced Help Sidebar.
511 \get_current_screen()->set_help_sidebar(
512 '<p><strong>' . \__( 'For more information:', 'activitypub' ) . '</strong></p>' . "\n" .
513 '<p><a href="https://wordpress.org/support/plugin/activitypub/">' . \esc_html__( 'Get support', 'activitypub' ) . '</a></p>' . "\n" .
514 '<p><a href="https://github.com/Automattic/wordpress-activitypub/issues">' . \esc_html__( 'Report an issue', 'activitypub' ) . '</a></p>' . "\n" .
515 '<p><a href="https://github.com/Automattic/wordpress-activitypub/tree/trunk/docs">' . \esc_html__( 'Documentation', 'activitypub' ) . '</a></p>' . "\n" .
516 '<p><a href="https://github.com/Automattic/wordpress-activitypub/releases">' . \esc_html__( 'View latest changes', 'activitypub' ) . '</a></p>'
517 );
518 }
519
520 /**
521 * Adds the ActivityPub help tab to the users page.
522 */
523 public static function add_users_help_tab() {
524 \get_current_screen()->add_help_tab(
525 array(
526 'id' => 'activitypub',
527 'title' => \__( 'ActivityPub', 'activitypub' ),
528 'content' => self::get_help_tab_template( 'users' ),
529 // Add to the end of the list.
530 'priority' => 20,
531 )
532 );
533 }
534
535 /**
536 * Handle 'welcome' query arg.
537 */
538 public static function handle_welcome_query_arg() {
539 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
540 if ( isset( $_GET['welcome'] ) ) {
541 // phpcs:ignore WordPress.Security.NonceVerification.Recommended
542 $welcome_checked = empty( \sanitize_text_field( \wp_unslash( $_GET['welcome'] ) ) ) ? 0 : 1;
543 \update_user_meta( \get_current_user_id(), 'activitypub_show_welcome_tab', $welcome_checked );
544 \wp_safe_redirect( \admin_url( 'options-general.php?page=activitypub&tab=settings' ) );
545 exit;
546 }
547 }
548
549 /**
550 * Add screen option.
551 *
552 * @param string $screen_settings The screen settings.
553 * @param object $screen The screen object.
554 *
555 * @return string The screen settings.
556 */
557 public static function add_screen_option( $screen_settings, $screen ) {
558 if ( 'settings_page_activitypub' !== $screen->id ) {
559 return $screen_settings;
560 }
561
562 // Verify screen options nonce.
563 if ( isset( $_POST['screenoptionnonce'] ) ) {
564 $nonce = \sanitize_text_field( \wp_unslash( $_POST['screenoptionnonce'] ) );
565 if ( ! \wp_verify_nonce( $nonce, 'screen-options-nonce' ) ) {
566 return $screen_settings;
567 }
568 }
569
570 $screen_options = array(
571 'activitypub_show_welcome_tab' => __( 'Welcome Page', 'activitypub' ),
572 'activitypub_show_advanced_tab' => __( 'Advanced Settings', 'activitypub' ),
573 );
574
575 /**
576 * Filters Activitypub settings screen options.
577 *
578 * @param string[] $screen_options Screen options. An array of user meta keys and screen option labels.
579 */
580 $screen_options = \apply_filters( 'activitypub_screen_options', $screen_options );
581 if ( empty( $screen_options ) ) {
582 return $screen_settings;
583 }
584
585 foreach ( $screen_options as $option => $label ) {
586 if ( isset( $_POST[ $option ] ) ) {
587 $value = \sanitize_text_field( \wp_unslash( $_POST[ $option ] ) );
588 \update_user_meta( \get_current_user_id(), $option, empty( $value ) ? 0 : 1 );
589 }
590 }
591
592 ob_start();
593 ?>
594 <fieldset>
595 <legend class="screen-layout"><?php \esc_html_e( 'Settings Pages', 'activitypub' ); ?></legend>
596 <p><?php \esc_html_e( 'Some settings pages can be shown or hidden by using the checkboxes.', 'activitypub' ); ?></p>
597 <div class="metabox-prefs-container">
598 <?php foreach ( $screen_options as $option => $label ) : ?>
599 <label for="<?php echo \esc_attr( $option ); ?>">
600 <input name="<?php echo \esc_attr( $option ); ?>" type="hidden" value="0" />
601 <input name="<?php echo \esc_attr( $option ); ?>" type="checkbox" id="<?php echo \esc_attr( $option ); ?>" value="1" <?php \checked( 1, \get_user_meta( \get_current_user_id(), $option, true ) ); ?> />
602 <?php echo \esc_html( $label ); ?>
603 </label>
604 <?php endforeach; ?>
605 </div>
606 </fieldset>
607 <?php
608
609 return ob_get_clean();
610 }
611
612 /**
613 * Show the submit button on the screen options page.
614 *
615 * @param bool $show_submit Whether to show the submit button.
616 * @param object $screen The screen object.
617 *
618 * @return bool Whether to show the submit button.
619 */
620 public static function screen_options_show_submit( $show_submit, $screen ) {
621 if ( 'settings_page_activitypub' !== $screen->id ) {
622 return $show_submit;
623 }
624
625 return true;
626 }
627
628 /**
629 * Returns an array of recommended plugins for ActivityPub.
630 */
631 public static function get_recommended_plugins() {
632 $plugins = array();
633
634 if ( ! \is_plugin_active( 'friends/friends.php' ) ) {
635 $plugins['friends'] = array(
636 'slug' => 'friends',
637 'author' => 'Alex Kirk',
638 'author_url' => 'https://profiles.wordpress.org/akirk/',
639 'icon' => 'https://ps.w.org/friends/assets/icon-256x256.png',
640 'name' => \__( 'Friends', 'activitypub' ),
641 'description' => \__( 'Follow people on Mastodon or similar platforms and display their posts on your WordPress, making your site a true Fediverse instance.', 'activitypub' ),
642 'install_url' => \admin_url( 'plugin-install.php?tab=plugin-information&plugin=friends&TB_iframe=true' ),
643 );
644 }
645
646 if ( ! \is_plugin_active( 'event-bridge-for-activitypub/event-bridge-for-activitypub.php' ) ) {
647 $plugins['event_bridge'] = array(
648 'slug' => 'event-bridge-for-activitypub',
649 'author' => 'André Menrath',
650 'author_url' => 'https://profiles.wordpress.org/andremenrath/',
651 'icon' => 'https://ps.w.org/event-bridge-for-activitypub/assets/icon-256x256.gif',
652 'name' => \__( 'Event Bridge for ActivityPub', 'activitypub' ),
653 'description' => \__( 'Make your events discoverable and federate them across decentralized platforms like Mastodon or Gancio.', 'activitypub' ),
654 'install_url' => \admin_url( 'plugin-install.php?tab=plugin-information&plugin=event-bridge-for-activitypub&TB_iframe=true' ),
655 );
656 }
657
658 if ( ! \is_plugin_active( 'enable-mastodon-apps/enable-mastodon-apps.php' ) ) {
659 $plugins['enable_mastodon_apps'] = array(
660 'slug' => 'enable-mastodon-apps',
661 'author' => 'Alex Kirk',
662 'author_url' => 'https://profiles.wordpress.org/akirk/',
663 'icon' => 'https://ps.w.org/enable-mastodon-apps/assets/icon-256x256.png',
664 'name' => \__( 'Enable Mastodon Apps', 'activitypub' ),
665 'description' => \__( 'Allow Mastodon apps to interact with your WordPress site, letting you write posts from your favorite app.', 'activitypub' ),
666 'install_url' => \admin_url( 'plugin-install.php?tab=plugin-information&plugin=enable-mastodon-apps&TB_iframe=true' ),
667 );
668 }
669
670 if ( ! \is_plugin_active( 'hum/hum.php' ) ) {
671 $plugins['hum'] = array(
672 'slug' => 'hum',
673 'author' => 'Will Norris',
674 'author_url' => 'https://profiles.wordpress.org/willnorris/',
675 'icon' => 'https://s.w.org/plugins/geopattern-icon/hum.svg',
676 'name' => \__( 'Hum', 'activitypub' ),
677 'description' => \__( 'A personal URL shortener for WordPress, perfect for sharing short links on the Fediverse.', 'activitypub' ),
678 'install_url' => \admin_url( 'plugin-install.php?tab=plugin-information&plugin=hum&TB_iframe=true' ),
679 );
680 }
681
682 if ( ! \is_plugin_active( 'webfinger/webfinger.php' ) ) {
683 $plugins['webfinger'] = array(
684 'slug' => 'webfinger',
685 'author' => 'Matthias Pfefferle',
686 'author_url' => 'https://profiles.wordpress.org/pfefferle/',
687 'icon' => 'https://ps.w.org/webfinger/assets/icon-256x256.png',
688 'name' => \__( 'WebFinger', 'activitypub' ),
689 'description' => \__( 'WebFinger protocol support for better discovery and compatibility.', 'activitypub' ),
690 'install_url' => \admin_url( 'plugin-install.php?tab=plugin-information&plugin=webfinger&TB_iframe=true' ),
691 );
692 }
693
694 if ( ! \is_plugin_active( 'nodeinfo/nodeinfo.php' ) ) {
695 $plugins['nodeinfo'] = array(
696 'slug' => 'nodeinfo',
697 'author' => 'Matthias Pfefferle',
698 'author_url' => 'https://profiles.wordpress.org/pfefferle/',
699 'icon' => 'https://ps.w.org/nodeinfo/assets/icon-256x256.png',
700 'name' => \__( 'NodeInfo', 'activitypub' ),
701 'description' => \__( 'Advanced NodeInfo protocol support for better discovery and compatibility.', 'activitypub' ),
702 'install_url' => \admin_url( 'plugin-install.php?tab=plugin-information&plugin=nodeinfo&TB_iframe=true' ),
703 );
704 }
705
706 return $plugins;
707 }
708
709 /**
710 * Render recommended plugins as a beautiful, rich showcase for the help tab.
711 */
712 public static function render_recommended_plugins_list() {
713 $plugins = self::get_recommended_plugins();
714
715 \ob_start();
716
717 echo '<div class="plugin-list widefat">';
718
719 foreach ( $plugins as $plugin ) :
720 ?>
721 <div class="plugin-card plugin-card-<?php echo \esc_attr( $plugin['slug'] ); ?>">
722 <div class="plugin-card-top">
723 <div class="name column-name">
724 <h3>
725 <a href="<?php echo \esc_url( $plugin['install_url'] ); ?>" class="thickbox open-plugin-details-modal">
726 <?php echo \esc_html( $plugin['name'] ); ?>
727 <img src="<?php echo \esc_url( $plugin['icon'] ); ?>" class="plugin-icon" alt="">
728 </a>
729 </h3>
730 </div>
731 <div class="action-links">
732 <ul class="plugin-action-buttons">
733 <li>
734 <a href="<?php echo \esc_url( $plugin['install_url'] ); ?>" class="button thickbox open-plugin-details-modal"><?php \esc_html_e( 'More Details', 'activitypub' ); ?></a>
735 </li>
736 </ul>
737 </div>
738 <div class="desc column-description">
739 <p><?php echo \esc_html( $plugin['description'] ); ?></p>
740 <p class="authors"> <cite>By <a href="<?php echo \esc_url( $plugin['author_url'] ); ?>"><?php echo \esc_html( $plugin['author'] ); ?></a></cite></p>
741 </div>
742 </div>
743 </div>
744 <?php
745 endforeach;
746
747 echo '</div>';
748
749 return \ob_get_clean();
750 }
751
752 /**
753 * Loads a help tab template.
754 *
755 * @param string $template_name The template file name (without ".php").
756 * @return string Rendered template output.
757 */
758 private static function get_help_tab_template( $template_name ) {
759 $template_path = ACTIVITYPUB_PLUGIN_DIR . 'templates/help-tab/' . $template_name . '.php';
760 if ( ! file_exists( $template_path ) ) {
761 return '';
762 }
763
764 ob_start();
765 load_template( $template_path, false );
766 return ob_get_clean();
767 }
768 }
769