PluginProbe
ActivityPub / 8.2.1
ActivityPub v8.2.1
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-options.php

class-options.php in ActivityPub 8.2.1, at includes/class-options.php

742 lines 19.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Options file.
4 *
5 * @package Activitypub
6 */
7
8 namespace Activitypub;
9
10 use Activitypub\Model\Blog;
11
12 /**
13 * Options class.
14 */
15 class Options {
16
17 /**
18 * Initialize the options.
19 */
20 public static function init() {
21 \add_action( 'admin_init', array( self::class, 'register_settings' ) );
22 \add_action( 'rest_api_init', array( self::class, 'register_settings' ) );
23
24 \add_filter( 'pre_option_activitypub_actor_mode', array( self::class, 'pre_option_activitypub_actor_mode' ) );
25 \add_filter( 'pre_option_activitypub_authorized_fetch', array( self::class, 'pre_option_activitypub_authorized_fetch' ) );
26 \add_filter( 'pre_option_activitypub_vary_header', array( self::class, 'pre_option_activitypub_vary_header' ) );
27 \add_filter( 'pre_option_activitypub_following_ui', array( self::class, 'pre_option_activitypub_following_ui' ) );
28 \add_filter( 'pre_option_activitypub_create_posts', array( self::class, 'pre_option_activitypub_create_posts' ) );
29
30 \add_filter( 'pre_option_activitypub_allow_likes', array( self::class, 'maybe_disable_interactions' ) );
31 \add_filter( 'pre_option_activitypub_allow_replies', array( self::class, 'maybe_disable_interactions' ) );
32
33 \add_filter( 'default_option_activitypub_negotiate_content', array( self::class, 'default_option_activitypub_negotiate_content' ) );
34 \add_filter( 'option_activitypub_max_image_attachments', array( self::class, 'default_max_image_attachments' ) );
35 \add_filter( 'option_activitypub_support_post_types', array( self::class, 'support_post_types_ensure_array' ) );
36 \add_filter( 'option_activitypub_object_type', array( self::class, 'default_object_type' ) );
37
38 \add_filter( 'option_activitypub_outbox_purge_days', array( self::class, 'sanitize_purge_days' ) );
39 \add_filter( 'option_activitypub_inbox_purge_days', array( self::class, 'sanitize_purge_days' ) );
40 \add_filter( 'option_activitypub_ap_post_purge_days', array( self::class, 'sanitize_purge_days' ) );
41
42 \add_action( 'update_option_activitypub_relay_mode', array( self::class, 'relay_mode_changed' ), 10, 2 );
43 }
44
45 /**
46 * Register ActivityPub settings.
47 */
48 public static function register_settings() {
49 /*
50 * Options Group: activitypub
51 */
52 \register_setting(
53 'activitypub',
54 'activitypub_post_content_type',
55 array(
56 'type' => 'string',
57 'description' => 'Use title and link, summary, full or custom content',
58 'show_in_rest' => array(
59 'schema' => array(
60 'enum' => array( 'title', 'excerpt', 'content' ),
61 ),
62 ),
63 'default' => 'content',
64 )
65 );
66
67 \register_setting(
68 'activitypub',
69 'activitypub_custom_post_content',
70 array(
71 'type' => 'string',
72 'description' => 'Define your own custom post template',
73 'show_in_rest' => true,
74 'default' => ACTIVITYPUB_CUSTOM_POST_CONTENT,
75 )
76 );
77
78 \register_setting(
79 'activitypub',
80 'activitypub_max_image_attachments',
81 array(
82 'type' => 'integer',
83 'description' => 'Number of images to attach to posts.',
84 'default' => ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS,
85 'sanitize_callback' => static function ( $value ) {
86 return \is_numeric( $value ) ? \absint( $value ) : ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS;
87 },
88 )
89 );
90
91 \register_setting(
92 'activitypub',
93 'activitypub_use_hashtags',
94 array(
95 'type' => 'boolean',
96 'description' => 'Add hashtags in the content as native tags and replace the #tag with the tag-link',
97 'default' => '0',
98 )
99 );
100
101 \register_setting(
102 'activitypub',
103 'activitypub_use_opengraph',
104 array(
105 'type' => 'boolean',
106 'description' => 'Automatically add "fediverse:creator" OpenGraph tags for Authors and the Blog-User.',
107 'default' => '1',
108 )
109 );
110
111 \register_setting(
112 'activitypub',
113 'activitypub_support_post_types',
114 array(
115 'type' => 'string',
116 'description' => 'Enable ActivityPub support for post types',
117 'show_in_rest' => true,
118 'default' => array( 'post' ),
119 )
120 );
121
122 \register_setting(
123 'activitypub',
124 'activitypub_actor_mode',
125 array(
126 'type' => 'string',
127 'description' => 'Choose your preferred Actor-Mode.',
128 'default' => ACTIVITYPUB_ACTOR_MODE,
129 'show_in_rest' => array(
130 'schema' => array(
131 'type' => 'string',
132 'enum' => array(
133 ACTIVITYPUB_ACTOR_MODE,
134 ACTIVITYPUB_BLOG_MODE,
135 ACTIVITYPUB_ACTOR_AND_BLOG_MODE,
136 ),
137 ),
138 ),
139 )
140 );
141
142 \register_setting(
143 'activitypub',
144 'activitypub_attribution_domains',
145 array(
146 'type' => 'string',
147 'description' => 'Websites allowed to credit you.',
148 'default' => home_host(),
149 'sanitize_callback' => array( Sanitize::class, 'host_list' ),
150 )
151 );
152
153 \register_setting(
154 'activitypub',
155 'activitypub_allow_likes',
156 array(
157 'type' => 'integer',
158 'description' => 'Allow likes.',
159 'default' => '1',
160 'sanitize_callback' => 'absint',
161 )
162 );
163
164 \register_setting(
165 'activitypub',
166 'activitypub_allow_reposts',
167 array(
168 'type' => 'integer',
169 'description' => 'Allow reposts.',
170 'default' => '1',
171 'sanitize_callback' => 'absint',
172 )
173 );
174
175 \register_setting(
176 'activitypub',
177 'activitypub_auto_approve_reactions',
178 array(
179 'type' => 'integer',
180 'description' => 'Auto-approve Reactions.',
181 'default' => '0',
182 'sanitize_callback' => 'absint',
183 )
184 );
185
186 \register_setting(
187 'activitypub',
188 'activitypub_default_quote_policy',
189 array(
190 'type' => 'string',
191 'description' => 'Default quote policy for new posts.',
192 'default' => ACTIVITYPUB_INTERACTION_POLICY_ANYONE,
193 'sanitize_callback' => static function ( $value ) {
194 $allowed = array(
195 ACTIVITYPUB_INTERACTION_POLICY_ANYONE,
196 ACTIVITYPUB_INTERACTION_POLICY_FOLLOWERS,
197 ACTIVITYPUB_INTERACTION_POLICY_ME,
198 );
199 return \in_array( $value, $allowed, true ) ? $value : ACTIVITYPUB_INTERACTION_POLICY_ANYONE;
200 },
201 )
202 );
203
204 \register_setting(
205 'activitypub',
206 'activitypub_relays',
207 array(
208 'type' => 'array',
209 'description' => 'Relays',
210 'default' => array(),
211 'sanitize_callback' => array( Sanitize::class, 'url_list' ),
212 )
213 );
214
215 \register_setting(
216 'activitypub',
217 'activitypub_site_blocked_actors',
218 array(
219 'type' => 'array',
220 'description' => 'Site-wide blocked ActivityPub actors.',
221 'default' => array(),
222 'sanitize_callback' => array( Sanitize::class, 'identifier_list' ),
223 )
224 );
225
226 /*
227 * Options Group: activitypub_advanced
228 */
229 \register_setting(
230 'activitypub_advanced',
231 'activitypub_outbox_purge_days',
232 array(
233 'type' => 'integer',
234 'description' => 'Number of days to keep items in the Outbox.',
235 'default' => ACTIVITYPUB_OUTBOX_PURGE_DAYS,
236 'sanitize_callback' => static function ( $value ) {
237 return \max( 1, \absint( $value ) );
238 },
239 )
240 );
241
242 \register_setting(
243 'activitypub_advanced',
244 'activitypub_inbox_purge_days',
245 array(
246 'type' => 'integer',
247 'description' => 'Number of days to keep items in the Inbox.',
248 'default' => ACTIVITYPUB_INBOX_PURGE_DAYS,
249 'sanitize_callback' => static function ( $value ) {
250 return \max( 1, \absint( $value ) );
251 },
252 )
253 );
254
255 \register_setting(
256 'activitypub_advanced',
257 'activitypub_ap_post_purge_days',
258 array(
259 'type' => 'integer',
260 'description' => 'Number of days to keep remote posts.',
261 'default' => ACTIVITYPUB_AP_POST_PURGE_DAYS,
262 'sanitize_callback' => static function ( $value ) {
263 return \max( 1, \absint( $value ) );
264 },
265 )
266 );
267
268 \register_setting(
269 'activitypub_advanced',
270 'activitypub_vary_header',
271 array(
272 'type' => 'boolean',
273 'description' => 'Add the Vary header to the ActivityPub response.',
274 'default' => true,
275 )
276 );
277
278 \register_setting(
279 'activitypub_advanced',
280 'activitypub_content_negotiation',
281 array(
282 'type' => 'boolean',
283 'description' => 'Enable content negotiation.',
284 'default' => true,
285 )
286 );
287
288 \register_setting(
289 'activitypub_advanced',
290 'activitypub_authorized_fetch',
291 array(
292 'type' => 'boolean',
293 'description' => 'Require HTTP signature authentication.',
294 'default' => false,
295 )
296 );
297
298 \register_setting(
299 'activitypub_advanced',
300 'activitypub_rfc9421_signature',
301 array(
302 'type' => 'boolean',
303 'description' => 'Use RFC-9421 signature.',
304 'default' => false,
305 )
306 );
307
308 \register_setting(
309 'activitypub_advanced',
310 'activitypub_following_ui',
311 array(
312 'type' => 'boolean',
313 'description' => 'Show Following UI in admin menus and settings.',
314 'default' => false,
315 )
316 );
317
318 \register_setting(
319 'activitypub_advanced',
320 'activitypub_reader_ui',
321 array(
322 'type' => 'boolean',
323 'description' => 'Enable the Reader to view posts from accounts you follow.',
324 'default' => false,
325 )
326 );
327
328 \register_setting(
329 'activitypub_advanced',
330 'activitypub_create_posts',
331 array(
332 'type' => 'boolean',
333 'description' => 'Allow creating posts via ActivityPub.',
334 'default' => false,
335 )
336 );
337
338 \register_setting(
339 'activitypub_advanced',
340 'activitypub_api',
341 array(
342 'type' => 'boolean',
343 'description' => 'Enable the ActivityPub API to allow third-party clients.',
344 'default' => false,
345 )
346 );
347
348 \register_setting(
349 'activitypub_advanced',
350 'activitypub_object_type',
351 array(
352 'type' => 'string',
353 'description' => 'The Activity-Object-Type',
354 'show_in_rest' => array(
355 'schema' => array(
356 'enum' => array( 'note', 'wordpress-post-format' ),
357 ),
358 ),
359 'default' => ACTIVITYPUB_DEFAULT_OBJECT_TYPE,
360 )
361 );
362
363 \register_setting(
364 'activitypub_advanced',
365 'activitypub_relay_mode',
366 array(
367 'type' => 'integer',
368 'description' => 'Enable relay mode to forward public activities to all followers.',
369 'default' => 0,
370 'sanitize_callback' => 'absint',
371 )
372 );
373
374 /*
375 * Options Group: activitypub_blog
376 */
377 \register_setting(
378 'activitypub_blog',
379 'activitypub_blog_description',
380 array(
381 'type' => 'string',
382 'description' => 'The Description of the Blog-User',
383 'show_in_rest' => true,
384 'default' => '',
385 )
386 );
387
388 \register_setting(
389 'activitypub_blog',
390 'activitypub_blog_identifier',
391 array(
392 'type' => 'string',
393 'description' => 'The Identifier of the Blog-User',
394 'show_in_rest' => true,
395 'default' => Blog::get_default_username(),
396 'sanitize_callback' => array( Sanitize::class, 'blog_identifier' ),
397 )
398 );
399
400 \register_setting(
401 'activitypub_blog',
402 'activitypub_header_image',
403 array(
404 'type' => 'integer',
405 'description' => 'The Attachment-ID of the Sites Header-Image',
406 'default' => null,
407 )
408 );
409
410 \register_setting(
411 'activitypub_blog',
412 'activitypub_blog_user_mailer_new_dm',
413 array(
414 'type' => 'integer',
415 'description' => 'Send a notification when someone sends a user of the blog a direct message.',
416 'default' => 1,
417 )
418 );
419
420 \register_setting(
421 'activitypub_blog',
422 'activitypub_blog_user_mailer_new_follower',
423 array(
424 'type' => 'integer',
425 'description' => 'Send a notification when someone starts to follow a user of the blog.',
426 'default' => 1,
427 )
428 );
429
430 \register_setting(
431 'activitypub_blog',
432 'activitypub_blog_user_mailer_new_mention',
433 array(
434 'type' => 'integer',
435 'description' => 'Send a notification when someone mentions a user of the blog.',
436 'default' => 1,
437 )
438 );
439
440 \register_setting(
441 'activitypub_blog',
442 'activitypub_mailer_annual_report',
443 array(
444 'type' => 'integer',
445 'description' => 'Send the annual Fediverse Year in Review email.',
446 'default' => 1,
447 )
448 );
449
450 \register_setting(
451 'activitypub_blog',
452 'activitypub_mailer_monthly_report',
453 array(
454 'type' => 'integer',
455 'description' => 'Send a monthly Fediverse stats report email.',
456 'default' => 0,
457 )
458 );
459
460 \register_setting(
461 'activitypub_blog',
462 'activitypub_blog_user_also_known_as',
463 array(
464 'type' => 'array',
465 'description' => 'An array of URLs that the blog user is known by.',
466 'default' => array(),
467 'sanitize_callback' => array( Sanitize::class, 'identifier_list' ),
468 )
469 );
470
471 \register_setting(
472 'activitypub_blog',
473 'activitypub_hide_social_graph',
474 array(
475 'type' => 'integer',
476 'description' => 'Hide Followers and Followings on Profile.',
477 'default' => 0,
478 'sanitize_callback' => 'absint',
479 'show_in_rest' => true,
480 )
481 );
482 }
483
484 /**
485 * Delete all options.
486 */
487 public static function delete() {
488 global $wpdb;
489
490 // phpcs:ignore WordPress.DB.DirectDatabaseQuery
491 $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'activitypub_%'" );
492 }
493
494 /**
495 * Pre-get option filter for the Actor-Mode.
496 *
497 * @param string|false $pre The pre-get option value.
498 *
499 * @return string|false The actor mode or false if it should not be filtered.
500 */
501 public static function pre_option_activitypub_actor_mode( $pre ) {
502 if ( \defined( 'ACTIVITYPUB_SINGLE_USER_MODE' ) && ACTIVITYPUB_SINGLE_USER_MODE ) {
503 return ACTIVITYPUB_BLOG_MODE;
504 }
505
506 if ( \defined( 'ACTIVITYPUB_DISABLE_USER' ) && ACTIVITYPUB_DISABLE_USER ) {
507 return ACTIVITYPUB_BLOG_MODE;
508 }
509
510 if ( \defined( 'ACTIVITYPUB_DISABLE_BLOG_USER' ) && ACTIVITYPUB_DISABLE_BLOG_USER ) {
511 return ACTIVITYPUB_ACTOR_MODE;
512 }
513
514 return $pre;
515 }
516
517 /**
518 * Pre-get option filter for the Authorized Fetch.
519 *
520 * @param string $pre The pre-get option value.
521 *
522 * @return string If the constant is defined, return the value, otherwise return the pre-get option value.
523 */
524 public static function pre_option_activitypub_authorized_fetch( $pre ) {
525 if ( ! \defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) ) {
526 return $pre;
527 }
528
529 if ( ACTIVITYPUB_AUTHORIZED_FETCH ) {
530 return '1';
531 }
532
533 return '0';
534 }
535
536 /**
537 * Pre-get option filter for the Vary Header.
538 *
539 * @param string $pre The pre-get option value.
540 *
541 * @return string If the constant is defined, return the value, otherwise return the pre-get option value.
542 */
543 public static function pre_option_activitypub_vary_header( $pre ) {
544 if ( ! \defined( 'ACTIVITYPUB_SEND_VARY_HEADER' ) ) {
545 return $pre;
546 }
547
548 if ( ACTIVITYPUB_SEND_VARY_HEADER ) {
549 return '1';
550 }
551
552 return '0';
553 }
554
555 /**
556 * Pre-get option filter for the Following UI.
557 *
558 * Forces the Following UI to be enabled when the Reader is enabled.
559 *
560 * @param string $pre The pre-get option value.
561 *
562 * @return string If the Reader is enabled, return '1', otherwise return the pre-get option value.
563 */
564 public static function pre_option_activitypub_following_ui( $pre ) {
565 /*
566 * Bypass the filter to get the actual stored value for activitypub_reader_ui.
567 * This avoids infinite loops if activitypub_reader_ui also had a pre_option filter.
568 */
569 if ( \get_option( 'activitypub_reader_ui', '0' ) ) {
570 return '1';
571 }
572
573 return $pre;
574 }
575
576 /**
577 * Pre-get option filter for the Create Posts setting.
578 *
579 * Forces the Create Posts setting to be enabled when the Reader is enabled.
580 *
581 * @param string $pre The pre-get option value.
582 *
583 * @return string If the Reader is enabled, return '1', otherwise return the pre-get option value.
584 */
585 public static function pre_option_activitypub_create_posts( $pre ) {
586 if ( \get_option( 'activitypub_reader_ui', '0' ) ) {
587 return '1';
588 }
589
590 return $pre;
591 }
592
593 /**
594 * Disallow interactions if the constant is set.
595 *
596 * @param bool $pre The value of the option.
597 *
598 * @return bool|string The value of the option.
599 */
600 public static function maybe_disable_interactions( $pre ) {
601 if ( ACTIVITYPUB_DISABLE_INCOMING_INTERACTIONS ) {
602 return '0';
603 }
604
605 return $pre;
606 }
607
608 /**
609 * Default option filter for the Content-Negotiation.
610 *
611 * @see https://github.com/Automattic/wordpress-activitypub/wiki/Caching
612 *
613 * @param string $default_value The default value of the option.
614 *
615 * @return string The default value of the option.
616 */
617 public static function default_option_activitypub_negotiate_content( $default_value ) {
618 $disable_for_plugins = array(
619 'wp-optimize/wp-optimize.php',
620 'wp-rocket/wp-rocket.php',
621 'w3-total-cache/w3-total-cache.php',
622 'wp-fastest-cache/wp-fastest-cache.php',
623 'sg-cachepress/sg-cachepress.php',
624 );
625
626 foreach ( $disable_for_plugins as $plugin ) {
627 if ( \is_plugin_active( $plugin ) ) {
628 return '0';
629 }
630 }
631
632 return $default_value;
633 }
634
635 /**
636 * Default max image attachments.
637 *
638 * @param string $value The value of the option.
639 *
640 * @return string|int The value of the option.
641 */
642 public static function default_max_image_attachments( $value ) {
643 if ( ! \is_numeric( $value ) ) {
644 $value = ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS;
645 }
646
647 return $value;
648 }
649
650 /**
651 * Ensure support post types is an array.
652 *
653 * @param string[] $value The value of the option.
654 *
655 * @return string[] The value of the option.
656 */
657 public static function support_post_types_ensure_array( $value ) {
658 return (array) $value;
659 }
660
661 /**
662 * Default object type.
663 *
664 * @param string $value The value of the option.
665 *
666 * @return string The value of the option.
667 */
668 public static function default_object_type( $value ) {
669 if ( ! $value ) {
670 $value = ACTIVITYPUB_DEFAULT_OBJECT_TYPE;
671 }
672
673 return $value;
674 }
675
676 /**
677 * Sanitize purge day values.
678 *
679 * Ensures the value is a non-negative integer. Returns the
680 * registered default when the stored value is empty or false
681 * (option not properly set), but allows 0 to disable purging.
682 *
683 * @since 8.1.0
684 *
685 * @param mixed $value The stored option value.
686 *
687 * @return int The sanitized value.
688 */
689 public static function sanitize_purge_days( $value ) {
690 if ( '' === $value || false === $value ) {
691 $filter = \current_filter();
692 $defaults = array(
693 'option_activitypub_outbox_purge_days' => ACTIVITYPUB_OUTBOX_PURGE_DAYS,
694 'option_activitypub_inbox_purge_days' => ACTIVITYPUB_INBOX_PURGE_DAYS,
695 'option_activitypub_ap_post_purge_days' => ACTIVITYPUB_AP_POST_PURGE_DAYS,
696 );
697
698 return $defaults[ $filter ] ?? ACTIVITYPUB_OUTBOX_PURGE_DAYS;
699 }
700
701 return \max( 1, \absint( $value ) );
702 }
703
704 /**
705 * Handle relay mode option changes.
706 *
707 * When relay mode is enabled, switch to blog-only mode and set username to "relay".
708 * When disabled, restore previous settings.
709 *
710 * @param mixed $old_value The old option value.
711 * @param mixed $new_value The new option value.
712 */
713 public static function relay_mode_changed( $old_value, $new_value ) {
714 if ( $new_value && ! $old_value ) {
715 // Enabling relay mode.
716 // Store previous username and actor mode for restoration.
717 \update_option( 'activitypub_relay_previous_blog_identifier', \get_option( 'activitypub_blog_identifier' ) );
718 \update_option( 'activitypub_relay_previous_actor_mode', \get_option( 'activitypub_actor_mode' ) );
719
720 // Set blog username to "relay".
721 \update_option( 'activitypub_blog_identifier', 'relay' );
722
723 // Switch to blog-only mode.
724 \update_option( 'activitypub_actor_mode', ACTIVITYPUB_BLOG_MODE );
725 } elseif ( ! $new_value && $old_value ) {
726 // Disabling relay mode - restore previous settings.
727 $previous_identifier = \get_option( 'activitypub_relay_previous_blog_identifier' );
728 $previous_actor_mode = \get_option( 'activitypub_relay_previous_actor_mode' );
729
730 if ( $previous_identifier ) {
731 \update_option( 'activitypub_blog_identifier', $previous_identifier );
732 \delete_option( 'activitypub_relay_previous_blog_identifier' );
733 }
734
735 if ( $previous_actor_mode ) {
736 \update_option( 'activitypub_actor_mode', $previous_actor_mode );
737 \delete_option( 'activitypub_relay_previous_actor_mode' );
738 }
739 }
740 }
741 }
742