Skip to content

Commit d226063

Browse files
pfefferlemattwiebe
andauthored
Add extra fields (#762)
* add extra fields settings * add settings * add settings link * allow users to only edit their extra fields * use nopaging instead of posts_per_page thanks @mattwiebe * load filters only on admin page and remove the view actions * author should not be editable * some improvements and extra informations * description * use nopaging instead * add blog url * formatting * formatting * some cosmetics * return attachments * formatting * formatting * add default extra fields * remove unused migration * better defaults handling * use a filter to be able to unhook/replace default extra fields * should fix #810 --------- Co-authored-by: Matt Wiebe <wiebe@automattic.com>
1 parent 4397ae9 commit d226063

11 files changed

+419
-66
lines changed

‎FEDERATION.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ The WordPress plugin largely follows ActivityPub's server-to-server specificatio
1616
- [FEP-5feb: Search indexing consent for actors](https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md)
1717
- [FEP-2677: Identifying the Application Actor](https://codeberg.org/fediverse/fep/src/branch/main/fep/2677/fep-2677.md)
1818
- [FEP-2c59: Discovery of a Webfinger address from an ActivityPub actor](https://codeberg.org/fediverse/fep/src/branch/main/fep/2c59/fep-2c59.md)
19+
- [FEP-fb2a: Actor metadata](https://codeberg.org/fediverse/fep/src/branch/main/fep/fb2a/fep-fb2a.md)
1920

2021
Partially supported FEPs
2122

‎includes/class-activitypub.php

+86-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public static function init() {
4545

4646
\add_action( 'in_plugin_update_message-' . ACTIVITYPUB_PLUGIN_BASENAME, array( self::class, 'plugin_update_message' ) );
4747

48+
\add_filter( 'activitypub_get_actor_extra_fields', array( self::class, 'default_actor_extra_fields' ), 10, 2 );
49+
4850
// register several post_types
4951
self::register_post_types();
5052
}
@@ -458,13 +460,43 @@ private static function register_post_types() {
458460
)
459461
);
460462

463+
\register_post_type(
464+
'ap_extrafield',
465+
array(
466+
'labels' => array(
467+
'name' => _x( 'Extra fields', 'post_type plural name', 'activitypub' ),
468+
'singular_name' => _x( 'Extra field', 'post_type single name', 'activitypub' ),
469+
'add_new' => __( 'Add new', 'activitypub' ),
470+
'add_new_item' => __( 'Add new extra field', 'activitypub' ),
471+
'new_item' => __( 'New extra field', 'activitypub' ),
472+
'edit_item' => __( 'Edit extra field', 'activitypub' ),
473+
'view_item' => __( 'View extra field', 'activitypub' ),
474+
'all_items' => __( 'All extra fields', 'activitypub' ),
475+
),
476+
'public' => false,
477+
'hierarchical' => false,
478+
'query_var' => false,
479+
'has_archive' => false,
480+
'publicly_queryable' => false,
481+
'show_in_menu' => false,
482+
'delete_with_user' => true,
483+
'can_export' => true,
484+
'exclude_from_search' => true,
485+
'show_in_rest' => true,
486+
'map_meta_cap' => true,
487+
'show_ui' => true,
488+
'supports' => array( 'title', 'editor' ),
489+
)
490+
);
491+
461492
\do_action( 'activitypub_after_register_post_type' );
462493
}
463494

464495
/**
465-
* Add the 'activitypub' query variable so WordPress won't mangle it.
496+
* Add the 'activitypub' capability to users who can publish posts.
466497
*
467498
* @param int $user_id User ID.
499+
*
468500
* @param array $userdata The raw array of data passed to wp_insert_user().
469501
*/
470502
public static function user_register( $user_id ) {
@@ -473,4 +505,57 @@ public static function user_register( $user_id ) {
473505
$user->add_cap( 'activitypub' );
474506
}
475507
}
508+
509+
/**
510+
* Add default extra fields to an actor.
511+
*
512+
* @param array $extra_fields The extra fields.
513+
* @param int $user_id The User-ID.
514+
*
515+
* @return array The extra fields.
516+
*/
517+
public static function default_actor_extra_fields( $extra_fields, $user_id ) {
518+
if ( $extra_fields ) {
519+
return $extra_fields;
520+
}
521+
522+
$already_migrated = \get_user_meta( $user_id, 'activitypub_default_extra_fields', true );
523+
524+
if ( $already_migrated ) {
525+
return $extra_fields;
526+
}
527+
528+
$defaults = array(
529+
\__( 'Blog', 'activitypub' ) => \home_url( '/' ),
530+
\__( 'Profile', 'activitypub' ) => \get_author_posts_url( $user_id ),
531+
\__( 'Homepage', 'activitypub' ) => \get_the_author_meta( 'user_url', $user_id ),
532+
);
533+
534+
foreach ( $defaults as $title => $url ) {
535+
if ( ! $url ) {
536+
continue;
537+
}
538+
539+
$extra_field = array(
540+
'post_type' => 'ap_extrafield',
541+
'post_title' => $title,
542+
'post_status' => 'publish',
543+
'post_author' => $user_id,
544+
'post_content' => sprintf(
545+
'<!-- wp:paragraph --><p><a rel="me" title="%s" target="_blank" href="%s">%s</a></p><!-- /wp:paragraph -->',
546+
\esc_attr( $url ),
547+
$url,
548+
\wp_parse_url( $url, \PHP_URL_HOST )
549+
),
550+
'comment_status' => 'closed',
551+
);
552+
553+
$extra_field_id = wp_insert_post( $extra_field );
554+
$extra_fields[] = get_post( $extra_field_id );
555+
}
556+
557+
\update_user_meta( $user_id, 'activitypub_default_extra_fields', true );
558+
559+
return $extra_fields;
560+
}
476561
}

‎includes/class-admin.php

+119-3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33

44
use WP_User_Query;
55
use Activitypub\Model\Blog;
6+
use Activitypub\Activitypub;
67
use Activitypub\Collection\Users;
78

89
use function Activitypub\count_followers;
910
use function Activitypub\is_user_disabled;
1011
use function Activitypub\was_comment_received;
1112
use function Activitypub\is_comment_federatable;
13+
use function Activitypub\add_default_actor_extra_fields;
1214

1315
/**
1416
* ActivityPub Admin Class
@@ -23,16 +25,21 @@ public static function init() {
2325
\add_action( 'admin_menu', array( self::class, 'admin_menu' ) );
2426
\add_action( 'admin_init', array( self::class, 'register_settings' ) );
2527
\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' ) );
2630
\add_action( 'personal_options_update', array( self::class, 'save_user_description' ) );
2731
\add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_scripts' ) );
2832
\add_action( 'admin_notices', array( self::class, 'admin_notices' ) );
2933

3034
\add_filter( 'comment_row_actions', array( self::class, 'comment_row_actions' ), 10, 2 );
3135
\add_filter( 'manage_edit-comments_columns', array( static::class, 'manage_comment_columns' ) );
32-
\add_filter( 'manage_comments_custom_column', array( static::class, 'manage_comments_custom_column' ), 9, 2 );
36+
\add_action( 'manage_comments_custom_column', array( static::class, 'manage_comments_custom_column' ), 9, 2 );
37+
38+
\add_filter( 'manage_posts_columns', array( static::class, 'manage_post_columns' ), 10, 2 );
39+
\add_action( 'manage_posts_custom_column', array( self::class, 'manage_posts_custom_column' ), 10, 2 );
3340

3441
\add_filter( 'manage_users_columns', array( self::class, 'manage_users_columns' ), 10, 1 );
35-
\add_filter( 'manage_users_custom_column', array( self::class, 'manage_users_custom_column' ), 10, 3 );
42+
\add_action( 'manage_users_custom_column', array( self::class, 'manage_users_custom_column' ), 10, 3 );
3643
\add_filter( 'bulk_actions-users', array( self::class, 'user_bulk_options' ) );
3744
\add_filter( 'handle_bulk_actions-users', array( self::class, 'handle_bulk_request' ), 10, 3 );
3845

@@ -62,6 +69,8 @@ public static function admin_menu() {
6269
$followers_list_page = \add_users_page( \__( 'Followers', 'activitypub' ), \__( 'Followers', 'activitypub' ), 'read', 'activitypub-followers-list', array( self::class, 'followers_list_page' ) );
6370

6471
\add_action( 'load-' . $followers_list_page, array( self::class, 'add_followers_list_help_tab' ) );
72+
73+
\add_users_page( \__( 'Extra Fields', 'activitypub' ), \__( 'Extra Fields', 'activitypub' ), 'read', esc_url( admin_url( '/edit.php?post_type=ap_extrafield' ) ) );
6574
}
6675
}
6776

@@ -76,6 +85,16 @@ public static function admin_notices() {
7685
$admin_notice = \__( 'You are using the ActivityPub plugin with a permalink structure of "plain". This will prevent ActivityPub from working. Please go to "Settings" / "Permalinks" and choose a permalink structure other than "plain".', 'activitypub' );
7786
self::show_admin_notice( $admin_notice, 'error' );
7887
}
88+
89+
$current_screen = get_current_screen();
90+
91+
if ( isset( $current_screen->id ) && 'edit-ap_extrafield' === $current_screen->id ) {
92+
?>
93+
<div class="notice" style="margin: 0; background: none; border: none; box-shadow: none; padding: 15px 0 0 0; font-size: 14px;">
94+
<?php 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' ); ?>
95+
</div>
96+
<?php
97+
}
7998
}
8099

81100
/**
@@ -353,6 +372,68 @@ function ( $allcaps, $caps, $arg ) {
353372
);
354373
}
355374

375+
public static function edit_post() {
376+
// Disable the edit_post capability for federated posts.
377+
\add_filter(
378+
'user_has_cap',
379+
function ( $allcaps, $caps, $arg ) {
380+
if ( 'edit_post' !== $arg[0] ) {
381+
return $allcaps;
382+
}
383+
384+
$post = get_post( $arg[2] );
385+
386+
if ( 'ap_extrafield' !== $post->post_type ) {
387+
return $allcaps;
388+
}
389+
390+
if ( (int) get_current_user_id() !== (int) $post->post_author ) {
391+
return false;
392+
}
393+
394+
return $allcaps;
395+
},
396+
1,
397+
3
398+
);
399+
}
400+
401+
/**
402+
* Add ActivityPub specific actions/filters to the post list view
403+
*
404+
* @return void
405+
*/
406+
public static function list_posts() {
407+
// Show only the user's extra fields.
408+
\add_action(
409+
'pre_get_posts',
410+
function ( $query ) {
411+
if ( $query->get( 'post_type' ) === 'ap_extrafield' ) {
412+
$query->set( 'author', get_current_user_id() );
413+
}
414+
}
415+
);
416+
417+
// Remove all views for the extra fields.
418+
$screen_id = get_current_screen()->id;
419+
420+
add_filter(
421+
"views_{$screen_id}",
422+
function ( $views ) {
423+
if ( 'ap_extrafield' === get_post_type() ) {
424+
return array();
425+
}
426+
427+
return $views;
428+
}
429+
);
430+
431+
// Set defaults for new extra fields.
432+
if ( 'edit-ap_extrafield' === $screen_id ) {
433+
Activitypub::default_actor_extra_fields( array(), get_current_user_id() );
434+
}
435+
}
436+
356437
public static function comment_row_actions( $actions, $comment ) {
357438
if ( was_comment_received( $comment ) ) {
358439
unset( $actions['edit'] );
@@ -382,12 +463,28 @@ public static function manage_users_columns( $columns ) {
382463
* @param array $columns the list of column names
383464
*/
384465
public static function manage_comment_columns( $columns ) {
385-
$columns['comment_type'] = esc_attr__( 'Comment-Type', 'activitypub' );
466+
$columns['comment_type'] = esc_attr__( 'Comment-Type', 'activitypub' );
386467
$columns['comment_protocol'] = esc_attr__( 'Protocol', 'activitypub' );
387468

388469
return $columns;
389470
}
390471

472+
/**
473+
* Add "post_content" as column for Extra-Fields in WP-Admin
474+
*
475+
* @param array $columns Tthe list of column names.
476+
* @param string $post_type The post type.
477+
*/
478+
public static function manage_post_columns( $columns, $post_type ) {
479+
if ( 'ap_extrafield' === $post_type ) {
480+
$after_key = 'title';
481+
$index = array_search( $after_key, array_keys( $columns ), true );
482+
$columns = array_slice( $columns, 0, $index + 1 ) + array( 'extra_field_content' => esc_attr__( 'Content', 'activitypub' ) ) + $columns;
483+
}
484+
485+
return $columns;
486+
}
487+
391488
/**
392489
* Add "comment-type" and "protocol" as column in WP-Admin
393490
*
@@ -429,6 +526,25 @@ public static function manage_users_custom_column( $output, $column_name, $user_
429526
}
430527
}
431528

529+
/**
530+
* Add a column "extra_field_content" to the post list view
531+
*
532+
* @param string $column_name The column name.
533+
* @param int $post_id The post ID.
534+
*
535+
* @return void
536+
*/
537+
public static function manage_posts_custom_column( $column_name, $post_id ) {
538+
$post = get_post( $post_id );
539+
540+
if ( 'extra_field_content' === $column_name ) {
541+
$post = get_post( $post_id );
542+
if ( 'ap_extrafield' === $post->post_type ) {
543+
echo esc_attr( wp_strip_all_tags( $post->post_content ) );
544+
}
545+
}
546+
}
547+
432548
/**
433549
* Add options to the Bulk dropdown on the users page
434550
*

‎includes/class-scheduler.php

+9-1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ public static function deregister_schedules() {
117117
public static function schedule_post_activity( $new_status, $old_status, $post ) {
118118
$post = get_post( $post );
119119

120+
if ( 'ap_extrafield' === $post->post_type ) {
121+
self::schedule_profile_update( $post->post_author );
122+
return;
123+
}
124+
120125
// Do not send activities if post is password protected.
121126
if ( \post_password_required( $post ) ) {
122127
return;
@@ -318,7 +323,9 @@ public static function user_update( $user_id ) {
318323

319324
/**
320325
* Theme mods only have a dynamic filter so we fudge it like this.
321-
* @param mixed $value
326+
*
327+
* @param mixed $value
328+
*
322329
* @return mixed
323330
*/
324331
public static function blog_user_update( $value = null ) {
@@ -328,6 +335,7 @@ public static function blog_user_update( $value = null ) {
328335

329336
/**
330337
* Send a profile update to all followers. Gets hooked into all relevant options/meta etc.
338+
*
331339
* @param int $user_id The user ID to update (Could be 0 for Blog-User).
332340
*/
333341
public static function schedule_profile_update( $user_id ) {

‎includes/class-webfinger.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public static function get_data( $uri ) {
190190
return $data;
191191
}
192192

193-
$webfinger_url = 'https://' . $host . '/.well-known/webfinger?resource=' . rawurlencode( $identifier );
193+
$webfinger_url = sprintf( 'https://%s/.well-known/webfinger?resource=%s', $host, rawurlencode( $identifier ) );
194194

195195
$response = wp_safe_remote_get(
196196
$webfinger_url,

0 commit comments

Comments
 (0)