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
activitypub / includes / wp-admin / class-settings.php

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

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