| 1 |
<?php |
| 2 |
/** |
| 3 |
* Advanced Settings Fields file. |
| 4 |
* |
| 5 |
* @package Activitypub |
| 6 |
*/ |
| 7 |
|
| 8 |
namespace Activitypub\WP_Admin; |
| 9 |
|
| 10 |
use Activitypub\Options; |
| 11 |
|
| 12 |
/** |
| 13 |
* Advanced Settings Fields class. |
| 14 |
*/ |
| 15 |
class Advanced_Settings_Fields { |
| 16 |
|
| 17 |
/** |
| 18 |
* Initialize. |
| 19 |
*/ |
| 20 |
public static function init() { |
| 21 |
\add_action( 'load-settings_page_activitypub', array( self::class, 'register_advanced_fields' ) ); |
| 22 |
} |
| 23 |
|
| 24 |
/** |
| 25 |
* Register settings. |
| 26 |
*/ |
| 27 |
public static function register_advanced_fields() { |
| 28 |
\add_settings_section( |
| 29 |
'activitypub_advanced_settings', |
| 30 |
\__( 'Advanced Settings', 'activitypub' ), |
| 31 |
array( self::class, 'render_advanced_settings_section' ), |
| 32 |
'activitypub_advanced_settings' |
| 33 |
); |
| 34 |
|
| 35 |
if ( ! Options::is_distribution_mode_locked() ) { |
| 36 |
\add_settings_field( |
| 37 |
'activitypub_distribution_mode', |
| 38 |
\__( 'Distribution Mode', 'activitypub' ), |
| 39 |
array( self::class, 'render_distribution_mode_field' ), |
| 40 |
'activitypub_advanced_settings', |
| 41 |
'activitypub_advanced_settings' |
| 42 |
); |
| 43 |
|
| 44 |
// phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 45 |
$current_tab = isset( $_GET['tab'] ) ? \sanitize_key( \wp_unslash( $_GET['tab'] ) ) : ''; |
| 46 |
if ( 'advanced' === $current_tab ) { |
| 47 |
\wp_enqueue_script( |
| 48 |
'activitypub-distribution-mode', |
| 49 |
\plugins_url( 'assets/js/activitypub-distribution-mode.js', ACTIVITYPUB_PLUGIN_FILE ), |
| 50 |
array(), |
| 51 |
ACTIVITYPUB_PLUGIN_VERSION, |
| 52 |
true |
| 53 |
); |
| 54 |
} |
| 55 |
} |
| 56 |
|
| 57 |
if ( ! \defined( 'ACTIVITYPUB_SEND_VARY_HEADER' ) ) { |
| 58 |
\add_settings_field( |
| 59 |
'activitypub_vary_header', |
| 60 |
\__( 'Vary Header', 'activitypub' ), |
| 61 |
array( self::class, 'render_vary_header_field' ), |
| 62 |
'activitypub_advanced_settings', |
| 63 |
'activitypub_advanced_settings', |
| 64 |
array( 'label_for' => 'activitypub_vary_header' ) |
| 65 |
); |
| 66 |
} |
| 67 |
|
| 68 |
\add_settings_field( |
| 69 |
'activitypub_content_negotiation', |
| 70 |
\__( 'Content Negotiation', 'activitypub' ), |
| 71 |
array( self::class, 'render_content_negotiation_field' ), |
| 72 |
'activitypub_advanced_settings', |
| 73 |
'activitypub_advanced_settings', |
| 74 |
array( 'label_for' => 'activitypub_content_negotiation' ) |
| 75 |
); |
| 76 |
|
| 77 |
if ( ! \defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) ) { |
| 78 |
\add_settings_field( |
| 79 |
'activitypub_authorized_fetch', |
| 80 |
\__( 'Authorized Fetch', 'activitypub' ), |
| 81 |
array( self::class, 'render_authorized_fetch_field' ), |
| 82 |
'activitypub_advanced_settings', |
| 83 |
'activitypub_advanced_settings', |
| 84 |
array( 'label_for' => 'activitypub_authorized_fetch' ) |
| 85 |
); |
| 86 |
} |
| 87 |
|
| 88 |
\add_settings_field( |
| 89 |
'activitypub_rfc9421_signature', |
| 90 |
\__( 'Modern Signature Format', 'activitypub' ), |
| 91 |
array( self::class, 'render_rfc9421_signature_field' ), |
| 92 |
'activitypub_advanced_settings', |
| 93 |
'activitypub_advanced_settings', |
| 94 |
array( 'label_for' => 'activitypub_rfc9421_signature' ) |
| 95 |
); |
| 96 |
|
| 97 |
\add_settings_field( |
| 98 |
'activitypub_following_ui', |
| 99 |
\__( 'Following User Interface', 'activitypub' ), |
| 100 |
array( self::class, 'render_following_ui_field' ), |
| 101 |
'activitypub_advanced_settings', |
| 102 |
'activitypub_advanced_settings', |
| 103 |
array( 'label_for' => 'activitypub_following_ui' ) |
| 104 |
); |
| 105 |
|
| 106 |
// Only offer the Reader opt-in where the app can actually boot (WordPress 7.0+). |
| 107 |
if ( App::is_supported() ) { |
| 108 |
\add_settings_field( |
| 109 |
'activitypub_reader_ui', |
| 110 |
\__( 'Reader', 'activitypub' ), |
| 111 |
array( self::class, 'render_reader_field' ), |
| 112 |
'activitypub_advanced_settings', |
| 113 |
'activitypub_advanced_settings', |
| 114 |
array( 'label_for' => 'activitypub_reader_ui' ) |
| 115 |
); |
| 116 |
} |
| 117 |
|
| 118 |
\add_settings_field( |
| 119 |
'activitypub_api', |
| 120 |
\__( 'ActivityPub API', 'activitypub' ), |
| 121 |
array( self::class, 'render_api_field' ), |
| 122 |
'activitypub_advanced_settings', |
| 123 |
'activitypub_advanced_settings', |
| 124 |
array( 'label_for' => 'activitypub_api' ) |
| 125 |
); |
| 126 |
|
| 127 |
\add_settings_field( |
| 128 |
'activitypub_object_type', |
| 129 |
\__( 'Activity-Object-Type', 'activitypub' ), |
| 130 |
array( self::class, 'render_object_type_field' ), |
| 131 |
'activitypub_advanced_settings', |
| 132 |
'activitypub_advanced_settings', |
| 133 |
array( 'label_for' => 'activitypub_object_type' ) |
| 134 |
); |
| 135 |
} |
| 136 |
|
| 137 |
/** |
| 138 |
* Render Advanced Settings Section. |
| 139 |
*/ |
| 140 |
public static function render_advanced_settings_section() { |
| 141 |
?> |
| 142 |
<p> |
| 143 |
<?php |
| 144 |
$allowed_html = array( |
| 145 |
'a' => array( |
| 146 |
'href' => true, |
| 147 |
'target' => true, |
| 148 |
), |
| 149 |
); |
| 150 |
echo \wp_kses( \__( 'Advanced settings allow deep customization but can affect your site’s functionality, security, or performance if misconfigured. Only proceed if you fully understand the changes, and always back up your site beforehand. If unsure, consult <a href="https://github.com/Automattic/wordpress-activitypub/tree/trunk/docs" target="_blank">documentation</a> or seek <a href="https://wordpress.org/support/plugin/activitypub/" target="_blank">expert advice</a>.', 'activitypub' ), $allowed_html ); |
| 151 |
?> |
| 152 |
</p> |
| 153 |
<?php |
| 154 |
} |
| 155 |
|
| 156 |
/** |
| 157 |
* Render vary header field. |
| 158 |
*/ |
| 159 |
public static function render_vary_header_field() { |
| 160 |
$value = \get_option( 'activitypub_vary_header', '1' ); |
| 161 |
?> |
| 162 |
<p> |
| 163 |
<label> |
| 164 |
<input type="checkbox" id="activitypub_vary_header" name="activitypub_vary_header" value="1" <?php \checked( '1', $value ); ?> /> |
| 165 |
<?php echo \wp_kses( \__( 'Help prevent incorrect caching of ActivityPub responses.', 'activitypub' ), array( 'code' => array() ) ); ?> |
| 166 |
</label> |
| 167 |
</p> |
| 168 |
<p class="description"> |
| 169 |
<?php \esc_html_e( 'Enable this if you notice your site showing technical content instead of normal web pages, or if your ActivityPub connections seem unreliable. This setting helps your site deliver the right format of content to different services automatically.', 'activitypub' ); ?> |
| 170 |
</p> |
| 171 |
<?php |
| 172 |
} |
| 173 |
|
| 174 |
/** |
| 175 |
* Render content negotiation field. |
| 176 |
*/ |
| 177 |
public static function render_content_negotiation_field() { |
| 178 |
$value = \get_option( 'activitypub_content_negotiation', '1' ); |
| 179 |
?> |
| 180 |
<p> |
| 181 |
<label> |
| 182 |
<input type="checkbox" id="activitypub_content_negotiation" name="activitypub_content_negotiation" value="1" <?php \checked( '1', $value ); ?> /> |
| 183 |
<?php \esc_html_e( 'Enable content negotiation for browsers and Fediverse services.', 'activitypub' ); ?> |
| 184 |
</label> |
| 185 |
</p> |
| 186 |
<p class="description"> |
| 187 |
<?php \esc_html_e( 'Content negotiation ensures your site displays regular web pages to browsers and machine-readable data to Fediverse services. Disable this if your site shows raw technical data to visitors or if ActivityPub connections have issues.', 'activitypub' ); ?> |
| 188 |
</p> |
| 189 |
<?php |
| 190 |
} |
| 191 |
|
| 192 |
/** |
| 193 |
* Render use Authorized Fetch field. |
| 194 |
*/ |
| 195 |
public static function render_authorized_fetch_field() { |
| 196 |
$value = \get_option( 'activitypub_authorized_fetch', '0' ); |
| 197 |
?> |
| 198 |
<p> |
| 199 |
<label> |
| 200 |
<input type="checkbox" id="activitypub_authorized_fetch" name="activitypub_authorized_fetch" value="1" <?php \checked( '1', $value ); ?> /> |
| 201 |
<?php \esc_html_e( 'Require HTTP signature authentication on ActivityPub representations of public posts and profiles.', 'activitypub' ); ?> |
| 202 |
</label> |
| 203 |
</p> |
| 204 |
<p class="description"> |
| 205 |
<?php \esc_html_e( 'âš Secure mode has its limitations, which is why it is not enabled by default. It is not fully supported by all software in the fediverse, and some features may break, especially when interacting with Mastodon servers older than version 3.0. Additionally, since it requires authentication for public content, caching is not possible, leading to higher computational costs.', 'activitypub' ); ?> |
| 206 |
</p> |
| 207 |
<p class="description"> |
| 208 |
<?php \esc_html_e( 'âš Secure mode does not hide the HTML representations of public posts and profiles. While HTML is a less consistent format (that potentially changes often) compared to first-class ActivityPub representations or the REST API, it still poses a potential risk for content scraping.', 'activitypub' ); ?> |
| 209 |
</p> |
| 210 |
<?php |
| 211 |
} |
| 212 |
|
| 213 |
/** |
| 214 |
* Render RFC-9421 signature field. |
| 215 |
*/ |
| 216 |
public static function render_rfc9421_signature_field() { |
| 217 |
$value = \get_option( 'activitypub_rfc9421_signature', '0' ); |
| 218 |
?> |
| 219 |
<p> |
| 220 |
<label> |
| 221 |
<input type="checkbox" id="activitypub_rfc9421_signature" name="activitypub_rfc9421_signature" value="1" <?php \checked( '1', $value ); ?> /> |
| 222 |
<?php \esc_html_e( 'Use modern signature format for Fediverse communications.', 'activitypub' ); ?> |
| 223 |
</label> |
| 224 |
</p> |
| 225 |
<p class="description"> |
| 226 |
<?php \esc_html_e( 'Enables a newer standard (RFC-9421) for verifying your site’s identity when communicating with other Fediverse platforms. This alternative signature format may cause compatibility issues with platforms that do not support it. Keep disabled if you experience connection problems with certain Fediverse servers.', 'activitypub' ); ?> |
| 227 |
</p> |
| 228 |
<?php |
| 229 |
} |
| 230 |
|
| 231 |
/** |
| 232 |
* Render show following UI field. |
| 233 |
*/ |
| 234 |
public static function render_following_ui_field() { |
| 235 |
$value = \get_option( 'activitypub_following_ui', '0' ); |
| 236 |
?> |
| 237 |
<p> |
| 238 |
<label> |
| 239 |
<input type="checkbox" id="activitypub_following_ui" name="activitypub_following_ui" value="1" <?php \checked( '1', $value ); ?> /> |
| 240 |
Display the "Following" interface in the admin menus and settings. |
| 241 |
</label> |
| 242 |
</p> |
| 243 |
<p class="description"> |
| 244 |
Activates the Following feature, letting you follow other ActivityPub accounts directly from your WordPress site. Adds a "Following" menu and tab to manage followed accounts. |
| 245 |
</p> |
| 246 |
<p class="description"> |
| 247 |
⚠A reader interface is not available yet. Please follow accounts sparingly—you won't be able to see their posts or shares. This feature is intended for testing the follow functionality. Once fully implemented, it will be enabled by default. |
| 248 |
</p> |
| 249 |
<?php |
| 250 |
} |
| 251 |
|
| 252 |
/** |
| 253 |
* Render reader field. |
| 254 |
*/ |
| 255 |
public static function render_reader_field() { |
| 256 |
$value = \get_option( 'activitypub_reader_ui', '0' ); |
| 257 |
?> |
| 258 |
<p> |
| 259 |
<label> |
| 260 |
<input type="checkbox" id="activitypub_reader_ui" name="activitypub_reader_ui" value="1" <?php \checked( '1', $value ); ?> /> |
| 261 |
Enable the Reader to view posts from accounts you follow. |
| 262 |
</label> |
| 263 |
</p> |
| 264 |
<p class="description"> |
| 265 |
Adds a "Social Web" interface where you can read posts and shares from accounts you follow. Also enables the Following feature. Look for it in Dashboard > Social Web. |
| 266 |
</p> |
| 267 |
<p class="description"> |
| 268 |
âš This feature is experimental and may change significantly in future updates. |
| 269 |
</p> |
| 270 |
<?php |
| 271 |
} |
| 272 |
|
| 273 |
/** |
| 274 |
* Render ActivityPub API field. |
| 275 |
*/ |
| 276 |
public static function render_api_field() { |
| 277 |
$value = \get_option( 'activitypub_api', '0' ); |
| 278 |
?> |
| 279 |
<p> |
| 280 |
<label> |
| 281 |
<input type="checkbox" id="activitypub_api" name="activitypub_api" value="1" <?php \checked( '1', $value ); ?> /> |
| 282 |
<?php \esc_html_e( 'Enable the ActivityPub API to connect third-party clients.', 'activitypub' ); ?> |
| 283 |
</label> |
| 284 |
</p> |
| 285 |
<p class="description"> |
| 286 |
<?php \esc_html_e( 'Enables OAuth 2.0 authentication so third-party ActivityPub clients (like Mastodon apps) can post, follow, and interact on your behalf. You can manage connected apps from your profile page.', 'activitypub' ); ?> |
| 287 |
</p> |
| 288 |
<p class="description"> |
| 289 |
<?php |
| 290 |
echo \wp_kses( |
| 291 |
\__( 'âš This feature is experimental and may change significantly in future updates.', 'activitypub' ), |
| 292 |
'data' |
| 293 |
); |
| 294 |
?> |
| 295 |
</p> |
| 296 |
<?php |
| 297 |
} |
| 298 |
|
| 299 |
/** |
| 300 |
* Render object type field. |
| 301 |
*/ |
| 302 |
public static function render_object_type_field() { |
| 303 |
$value = \get_option( 'activitypub_object_type', ACTIVITYPUB_DEFAULT_OBJECT_TYPE ); |
| 304 |
?> |
| 305 |
<p> |
| 306 |
<label> |
| 307 |
<input type="checkbox" name="activitypub_object_type" value="note" <?php \checked( 'note', $value ); ?> /> |
| 308 |
<?php \esc_html_e( 'Use Template Tags instead of letting the plugin choose the best possible format for you.', 'activitypub' ); ?> |
| 309 |
</label> |
| 310 |
</p> |
| 311 |
<p class="description"> |
| 312 |
<?php \esc_html_e( 'This is mainly for backwards compatibility. It is not recommended to use the Template Tags, because it might not be supported in future versions.', 'activitypub' ); ?> |
| 313 |
</p> |
| 314 |
<?php |
| 315 |
} |
| 316 |
|
| 317 |
/** |
| 318 |
* Render distribution mode field. |
| 319 |
* |
| 320 |
* @since 9.0.0 |
| 321 |
*/ |
| 322 |
public static function render_distribution_mode_field() { |
| 323 |
$mode = \get_option( 'activitypub_distribution_mode', 'default' ); |
| 324 |
|
| 325 |
// Use centralized presets and add the custom option for the UI. |
| 326 |
$modes = Options::get_distribution_modes(); |
| 327 |
$modes['custom'] = array( |
| 328 |
'label' => \__( 'Custom', 'activitypub' ), |
| 329 |
'description' => \__( 'Configure batch size and delay manually.', 'activitypub' ), |
| 330 |
); |
| 331 |
|
| 332 |
// Custom fields fall back to the default preset values when unset. |
| 333 |
$custom_batch = \get_option( 'activitypub_custom_batch_size', $modes['default']['batch_size'] ); |
| 334 |
$custom_pause = \get_option( 'activitypub_custom_batch_pause', $modes['default']['pause'] ); |
| 335 |
|
| 336 |
?> |
| 337 |
<fieldset> |
| 338 |
<legend class="screen-reader-text"><span><?php \esc_html_e( 'Distribution Mode', 'activitypub' ); ?></span></legend> |
| 339 |
<p class="description"> |
| 340 |
<?php \esc_html_e( 'Controls how quickly the plugin sends posts to followers. Slower modes reduce server load but delay delivery.', 'activitypub' ); ?> |
| 341 |
</p> |
| 342 |
<?php |
| 343 |
foreach ( $modes as $key => $data ) { |
| 344 |
?> |
| 345 |
<p> |
| 346 |
<label> |
| 347 |
<input type="radio" name="activitypub_distribution_mode" value="<?php echo \esc_attr( $key ); ?>" <?php \checked( $key, $mode ); ?> /> |
| 348 |
<strong><?php echo \esc_html( $data['label'] ); ?></strong> |
| 349 |
</label> |
| 350 |
<br /> |
| 351 |
<?php echo \wp_kses( $data['description'], array( 'code' => array() ) ); ?> |
| 352 |
</p> |
| 353 |
<?php |
| 354 |
} |
| 355 |
|
| 356 |
/* |
| 357 |
* The custom fields are rendered visible so they remain usable when |
| 358 |
* JavaScript is disabled. The accompanying script collapses them on |
| 359 |
* page load when the active mode is not "custom" and toggles them |
| 360 |
* as the radio changes. |
| 361 |
*/ |
| 362 |
?> |
| 363 |
<ul id="activitypub-custom-distribution-fields"> |
| 364 |
<li> |
| 365 |
<label> |
| 366 |
<?php \esc_html_e( 'Batch size:', 'activitypub' ); ?> |
| 367 |
<input type="number" name="activitypub_custom_batch_size" value="<?php echo \esc_attr( $custom_batch ); ?>" min="1" step="1" class="small-text" /> |
| 368 |
</label> |
| 369 |
</li> |
| 370 |
<li> |
| 371 |
<label> |
| 372 |
<?php \esc_html_e( 'Pause between batches (seconds):', 'activitypub' ); ?> |
| 373 |
<input type="number" name="activitypub_custom_batch_pause" value="<?php echo \esc_attr( $custom_pause ); ?>" min="0" step="1" class="small-text" /> |
| 374 |
</label> |
| 375 |
</li> |
| 376 |
</ul> |
| 377 |
<p class="description"> |
| 378 |
<?php \esc_html_e( 'With many followers, slower modes may delay delivery. For example, Eco Mode with 1,000 followers takes approximately 25 minutes per post.', 'activitypub' ); ?> |
| 379 |
</p> |
| 380 |
</fieldset> |
| 381 |
<?php |
| 382 |
} |
| 383 |
} |
| 384 |
|