updated plugin ActivityPub version 2.6.1

This commit is contained in:
2024-07-19 19:46:05 +00:00
committed by Gitium
parent 19e351ef3b
commit 3b4e169a1e
39 changed files with 718 additions and 143 deletions

View File

@ -94,7 +94,7 @@ class Activity_Dispatcher {
* @return void
*/
public static function send_announce( $wp_object, $type ) {
if ( ! in_array( $type, array( 'Create', 'Update' ), true ) ) {
if ( ! in_array( $type, array( 'Create', 'Update', 'Delete' ), true ) ) {
return;
}

View File

@ -45,6 +45,8 @@ class Activitypub {
\add_action( 'in_plugin_update_message-' . ACTIVITYPUB_PLUGIN_BASENAME, array( self::class, 'plugin_update_message' ) );
\add_filter( 'activitypub_get_actor_extra_fields', array( self::class, 'default_actor_extra_fields' ), 10, 2 );
// register several post_types
self::register_post_types();
}
@ -458,13 +460,43 @@ class Activitypub {
)
);
\register_post_type(
'ap_extrafield',
array(
'labels' => array(
'name' => _x( 'Extra fields', 'post_type plural name', 'activitypub' ),
'singular_name' => _x( 'Extra field', 'post_type single name', 'activitypub' ),
'add_new' => __( 'Add new', 'activitypub' ),
'add_new_item' => __( 'Add new extra field', 'activitypub' ),
'new_item' => __( 'New extra field', 'activitypub' ),
'edit_item' => __( 'Edit extra field', 'activitypub' ),
'view_item' => __( 'View extra field', 'activitypub' ),
'all_items' => __( 'All extra fields', 'activitypub' ),
),
'public' => false,
'hierarchical' => false,
'query_var' => false,
'has_archive' => false,
'publicly_queryable' => false,
'show_in_menu' => false,
'delete_with_user' => true,
'can_export' => true,
'exclude_from_search' => true,
'show_in_rest' => true,
'map_meta_cap' => true,
'show_ui' => true,
'supports' => array( 'title', 'editor' ),
)
);
\do_action( 'activitypub_after_register_post_type' );
}
/**
* Add the 'activitypub' query variable so WordPress won't mangle it.
* Add the 'activitypub' capability to users who can publish posts.
*
* @param int $user_id User ID.
*
* @param array $userdata The raw array of data passed to wp_insert_user().
*/
public static function user_register( $user_id ) {
@ -473,4 +505,57 @@ class Activitypub {
$user->add_cap( 'activitypub' );
}
}
/**
* Add default extra fields to an actor.
*
* @param array $extra_fields The extra fields.
* @param int $user_id The User-ID.
*
* @return array The extra fields.
*/
public static function default_actor_extra_fields( $extra_fields, $user_id ) {
if ( $extra_fields || ! $user_id ) {
return $extra_fields;
}
$already_migrated = \get_user_meta( $user_id, 'activitypub_default_extra_fields', true );
if ( $already_migrated ) {
return $extra_fields;
}
$defaults = array(
\__( 'Blog', 'activitypub' ) => \home_url( '/' ),
\__( 'Profile', 'activitypub' ) => \get_author_posts_url( $user_id ),
\__( 'Homepage', 'activitypub' ) => \get_the_author_meta( 'user_url', $user_id ),
);
foreach ( $defaults as $title => $url ) {
if ( ! $url ) {
continue;
}
$extra_field = array(
'post_type' => 'ap_extrafield',
'post_title' => $title,
'post_status' => 'publish',
'post_author' => $user_id,
'post_content' => sprintf(
'<!-- wp:paragraph --><p><a rel="me" title="%s" target="_blank" href="%s">%s</a></p><!-- /wp:paragraph -->',
\esc_attr( $url ),
$url,
\wp_parse_url( $url, \PHP_URL_HOST )
),
'comment_status' => 'closed',
);
$extra_field_id = wp_insert_post( $extra_field );
$extra_fields[] = get_post( $extra_field_id );
}
\update_user_meta( $user_id, 'activitypub_default_extra_fields', true );
return $extra_fields;
}
}

View File

@ -3,12 +3,14 @@ namespace Activitypub;
use WP_User_Query;
use Activitypub\Model\Blog;
use Activitypub\Activitypub;
use Activitypub\Collection\Users;
use function Activitypub\count_followers;
use function Activitypub\is_user_disabled;
use function Activitypub\was_comment_received;
use function Activitypub\is_comment_federatable;
use function Activitypub\add_default_actor_extra_fields;
/**
* ActivityPub Admin Class
@ -23,16 +25,21 @@ class Admin {
\add_action( 'admin_menu', array( self::class, 'admin_menu' ) );
\add_action( 'admin_init', array( self::class, 'register_settings' ) );
\add_action( 'load-comment.php', array( self::class, 'edit_comment' ) );
\add_action( 'load-post.php', array( self::class, 'edit_post' ) );
\add_action( 'load-edit.php', array( self::class, 'list_posts' ) );
\add_action( 'personal_options_update', array( self::class, 'save_user_description' ) );
\add_action( 'admin_enqueue_scripts', array( self::class, 'enqueue_scripts' ) );
\add_action( 'admin_notices', array( self::class, 'admin_notices' ) );
\add_filter( 'comment_row_actions', array( self::class, 'comment_row_actions' ), 10, 2 );
\add_filter( 'manage_edit-comments_columns', array( static::class, 'manage_comment_columns' ) );
\add_filter( 'manage_comments_custom_column', array( static::class, 'manage_comments_custom_column' ), 9, 2 );
\add_action( 'manage_comments_custom_column', array( static::class, 'manage_comments_custom_column' ), 9, 2 );
\add_filter( 'manage_posts_columns', array( static::class, 'manage_post_columns' ), 10, 2 );
\add_action( 'manage_posts_custom_column', array( self::class, 'manage_posts_custom_column' ), 10, 2 );
\add_filter( 'manage_users_columns', array( self::class, 'manage_users_columns' ), 10, 1 );
\add_filter( 'manage_users_custom_column', array( self::class, 'manage_users_custom_column' ), 10, 3 );
\add_action( 'manage_users_custom_column', array( self::class, 'manage_users_custom_column' ), 10, 3 );
\add_filter( 'bulk_actions-users', array( self::class, 'user_bulk_options' ) );
\add_filter( 'handle_bulk_actions-users', array( self::class, 'handle_bulk_request' ), 10, 3 );
@ -62,6 +69,8 @@ class Admin {
$followers_list_page = \add_users_page( \__( 'Followers', 'activitypub' ), \__( 'Followers', 'activitypub' ), 'read', 'activitypub-followers-list', array( self::class, 'followers_list_page' ) );
\add_action( 'load-' . $followers_list_page, array( self::class, 'add_followers_list_help_tab' ) );
\add_users_page( \__( 'Extra Fields', 'activitypub' ), \__( 'Extra Fields', 'activitypub' ), 'read', esc_url( admin_url( '/edit.php?post_type=ap_extrafield' ) ) );
}
}
@ -76,6 +85,16 @@ class Admin {
$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' );
self::show_admin_notice( $admin_notice, 'error' );
}
$current_screen = get_current_screen();
if ( isset( $current_screen->id ) && 'edit-ap_extrafield' === $current_screen->id ) {
?>
<div class="notice" style="margin: 0; background: none; border: none; box-shadow: none; padding: 15px 0 0 0; font-size: 14px;">
<?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' ); ?>
</div>
<?php
}
}
/**
@ -353,6 +372,68 @@ class Admin {
);
}
public static function edit_post() {
// Disable the edit_post capability for federated posts.
\add_filter(
'user_has_cap',
function ( $allcaps, $caps, $arg ) {
if ( 'edit_post' !== $arg[0] ) {
return $allcaps;
}
$post = get_post( $arg[2] );
if ( 'ap_extrafield' !== $post->post_type ) {
return $allcaps;
}
if ( (int) get_current_user_id() !== (int) $post->post_author ) {
return false;
}
return $allcaps;
},
1,
3
);
}
/**
* Add ActivityPub specific actions/filters to the post list view
*
* @return void
*/
public static function list_posts() {
// Show only the user's extra fields.
\add_action(
'pre_get_posts',
function ( $query ) {
if ( $query->get( 'post_type' ) === 'ap_extrafield' ) {
$query->set( 'author', get_current_user_id() );
}
}
);
// Remove all views for the extra fields.
$screen_id = get_current_screen()->id;
add_filter(
"views_{$screen_id}",
function ( $views ) {
if ( 'ap_extrafield' === get_post_type() ) {
return array();
}
return $views;
}
);
// Set defaults for new extra fields.
if ( 'edit-ap_extrafield' === $screen_id ) {
Activitypub::default_actor_extra_fields( array(), get_current_user_id() );
}
}
public static function comment_row_actions( $actions, $comment ) {
if ( was_comment_received( $comment ) ) {
unset( $actions['edit'] );
@ -382,12 +463,28 @@ class Admin {
* @param array $columns the list of column names
*/
public static function manage_comment_columns( $columns ) {
$columns['comment_type'] = esc_attr__( 'Comment-Type', 'activitypub' );
$columns['comment_type'] = esc_attr__( 'Comment-Type', 'activitypub' );
$columns['comment_protocol'] = esc_attr__( 'Protocol', 'activitypub' );
return $columns;
}
/**
* Add "post_content" as column for Extra-Fields in WP-Admin
*
* @param array $columns Tthe list of column names.
* @param string $post_type The post type.
*/
public static function manage_post_columns( $columns, $post_type ) {
if ( 'ap_extrafield' === $post_type ) {
$after_key = 'title';
$index = array_search( $after_key, array_keys( $columns ), true );
$columns = array_slice( $columns, 0, $index + 1 ) + array( 'extra_field_content' => esc_attr__( 'Content', 'activitypub' ) ) + $columns;
}
return $columns;
}
/**
* Add "comment-type" and "protocol" as column in WP-Admin
*
@ -423,9 +520,28 @@ class Admin {
}
if ( \user_can( $user_id, 'activitypub' ) ) {
return '&#x2713;';
return '<span aria-hidden="true">&#x2713;</span><span class="screen-reader-text">' . esc_html__( 'ActivityPub enabled for this author', 'activitypub' ) . '</span>';
} else {
return '&#x2717;';
return '<span aria-hidden="true">&#x2717;</span><span class="screen-reader-text">' . esc_html__( 'ActivityPub disabled for this author', 'activitypub' ) . '</span>';
}
}
/**
* Add a column "extra_field_content" to the post list view
*
* @param string $column_name The column name.
* @param int $post_id The post ID.
*
* @return void
*/
public static function manage_posts_custom_column( $column_name, $post_id ) {
$post = get_post( $post_id );
if ( 'extra_field_content' === $column_name ) {
$post = get_post( $post_id );
if ( 'ap_extrafield' === $post->post_type ) {
echo esc_attr( wp_strip_all_tags( $post->post_content ) );
}
}
}

View File

@ -241,7 +241,7 @@ class Comment {
*
* @param string $id ActivityPub object ID (usually a URL) to check.
*
* @return int|boolean Comment ID, or false on failure.
* @return \WP_Comment|false Comment object, or false on failure.
*/
public static function object_id_to_comment( $id ) {
$comment_query = new WP_Comment_Query(

View File

@ -118,7 +118,7 @@ class Migration {
// schedule the async migration
if ( ! \wp_next_scheduled( 'activitypub_migrate', $version_from_db ) ) {
\wp_schedule_single_event( \time(), 'activitypub_migrate', $version_from_db );
\wp_schedule_single_event( \time(), 'activitypub_migrate', array( $version_from_db ) );
}
if ( version_compare( $version_from_db, '0.17.0', '<' ) ) {
self::migrate_from_0_16();

View File

@ -117,6 +117,11 @@ class Scheduler {
public static function schedule_post_activity( $new_status, $old_status, $post ) {
$post = get_post( $post );
if ( 'ap_extrafield' === $post->post_type ) {
self::schedule_profile_update( $post->post_author );
return;
}
// Do not send activities if post is password protected.
if ( \post_password_required( $post ) ) {
return;
@ -130,9 +135,16 @@ class Scheduler {
$type = false;
if ( 'publish' === $new_status && 'publish' !== $old_status ) {
if (
'publish' === $new_status &&
'publish' !== $old_status
) {
$type = 'Create';
} elseif ( 'publish' === $new_status ) {
} elseif (
'publish' === $new_status ||
( 'draft' === $new_status &&
'draft' !== $old_status )
) {
$type = 'Update';
} elseif ( 'trash' === $new_status ) {
$type = 'Delete';
@ -311,7 +323,9 @@ class Scheduler {
/**
* Theme mods only have a dynamic filter so we fudge it like this.
* @param mixed $value
*
* @param mixed $value
*
* @return mixed
*/
public static function blog_user_update( $value = null ) {
@ -321,6 +335,7 @@ class Scheduler {
/**
* Send a profile update to all followers. Gets hooked into all relevant options/meta etc.
*
* @param int $user_id The user ID to update (Could be 0 for Blog-User).
*/
public static function schedule_profile_update( $user_id ) {

View File

@ -46,7 +46,10 @@ class Webfinger {
return new WP_Error(
'webfinger_missing_links',
__( 'No valid Link elements found.', 'activitypub' ),
$data
array(
'status' => 400,
'data' => $data,
)
);
}
@ -65,7 +68,10 @@ class Webfinger {
return new WP_Error(
'webfinger_url_no_activitypub',
__( 'The Site supports WebFinger but not ActivityPub', 'activitypub' ),
$data
array(
'status' => 400,
'data' => $data,
)
);
}
@ -103,7 +109,10 @@ class Webfinger {
return new WP_Error(
'webfinger_url_no_acct',
__( 'No acct URI found.', 'activitypub' ),
$data
array(
'status' => 400,
'data' => $data,
)
);
}
@ -117,6 +126,17 @@ class Webfinger {
* identifier and host as values
*/
public static function get_identifier_and_host( $url ) {
if ( ! $url ) {
return new WP_Error(
'webfinger_invalid_identifier',
__( 'Invalid Identifier', 'activitypub' ),
array(
'status' => 400,
'data' => $url,
)
);
}
// remove leading @
$url = ltrim( $url, '@' );
@ -144,7 +164,14 @@ class Webfinger {
}
if ( empty( $host ) ) {
return new WP_Error( 'webfinger_invalid_identifier', __( 'Invalid Identifier', 'activitypub' ) );
return new WP_Error(
'webfinger_invalid_identifier',
__( 'Invalid Identifier', 'activitypub' ),
array(
'status' => 400,
'data' => $url,
)
);
}
return array( $identifier, $host );
@ -174,7 +201,7 @@ class Webfinger {
return $data;
}
$webfinger_url = 'https://' . $host . '/.well-known/webfinger?resource=' . rawurlencode( $identifier );
$webfinger_url = sprintf( 'https://%s/.well-known/webfinger?resource=%s', $host, rawurlencode( $identifier ) );
$response = wp_safe_remote_get(
$webfinger_url,
@ -187,7 +214,10 @@ class Webfinger {
return new WP_Error(
'webfinger_url_not_accessible',
__( 'The WebFinger Resource is not accessible.', 'activitypub' ),
$webfinger_url
array(
'status' => 400,
'data' => $webfinger_url,
)
);
}
@ -215,7 +245,10 @@ class Webfinger {
return new WP_Error(
'webfinger_missing_links',
__( 'No valid Link elements found.', 'activitypub' ),
$data
array(
'status' => 400,
'data' => $data,
)
);
}
@ -228,7 +261,10 @@ class Webfinger {
return new WP_Error(
'webfinger_missing_remote_follow_endpoint',
__( 'No valid Remote-Follow endpoint found.', 'activitypub' ),
$data
array(
'status' => 400,
'data' => $data,
)
);
}

View File

@ -54,10 +54,12 @@ class Interactions {
return false;
}
$url = object_to_uri( $meta['url'] );
$commentdata = array(
'comment_post_ID' => $comment_post_id,
'comment_author' => isset( $meta['name'] ) ? \esc_attr( $meta['name'] ) : \esc_attr( $meta['preferredUsername'] ),
'comment_author_url' => \esc_url_raw( $meta['url'] ),
'comment_author_url' => \esc_url_raw( $url ),
'comment_content' => \addslashes( $activity['object']['content'] ),
'comment_type' => 'comment',
'comment_author_email' => '',
@ -73,7 +75,7 @@ class Interactions {
}
if ( isset( $activity['object']['url'] ) ) {
$commentdata['comment_meta']['source_url'] = \esc_url_raw( $activity['object']['url'] );
$commentdata['comment_meta']['source_url'] = \esc_url_raw( object_to_uri( $activity['object']['url'] ) );
}
// disable flood control
@ -198,7 +200,7 @@ class Interactions {
// get URL, because $actor seems to be the ID
if ( $meta && ! is_wp_error( $meta ) && isset( $meta['url'] ) ) {
$actor = $meta['url'];
$actor = object_to_uri( $meta['url'] );
}
$args = array(

View File

@ -8,6 +8,8 @@ use Activitypub\Model\Blog;
use Activitypub\Model\Application;
use function Activitypub\object_to_uri;
use function Activitypub\normalize_url;
use function Activitypub\normalize_host;
use function Activitypub\url_to_authorid;
use function Activitypub\is_user_disabled;
@ -80,12 +82,13 @@ class Users {
// check for application user.
if ( 'application' === $username ) {
return self::get_by_id( self::APPLICATION_USER_ID );
return new Application();
}
// check for 'activitypub_username' meta
$user = new WP_User_Query(
array(
'count_total' => false,
'number' => 1,
'hide_empty' => true,
'fields' => 'ID',
@ -110,6 +113,7 @@ class Users {
// check for login or nicename.
$user = new WP_User_Query(
array(
'count_total' => false,
'search' => $username,
'search_columns' => array( 'user_login', 'user_nicename' ),
'number' => 1,
@ -180,8 +184,8 @@ class Users {
// check for http(s)://blog.example.com/
if (
self::normalize_url( site_url() ) === self::normalize_url( $resource ) ||
self::normalize_url( home_url() ) === self::normalize_url( $resource )
normalize_url( site_url() ) === normalize_url( $resource ) ||
normalize_url( home_url() ) === normalize_url( $resource )
) {
return self::get_by_id( self::BLOG_USER_ID );
}
@ -195,8 +199,8 @@ class Users {
case 'acct':
$resource = \str_replace( 'acct:', '', $resource );
$identifier = \substr( $resource, 0, \strrpos( $resource, '@' ) );
$host = self::normalize_host( \substr( \strrchr( $resource, '@' ), 1 ) );
$blog_host = self::normalize_host( \wp_parse_url( \home_url( '/' ), \PHP_URL_HOST ) );
$host = normalize_host( \substr( \strrchr( $resource, '@' ), 1 ) );
$blog_host = normalize_host( \wp_parse_url( \home_url( '/' ), \PHP_URL_HOST ) );
if ( $blog_host !== $host ) {
return new WP_Error(
@ -251,33 +255,6 @@ class Users {
return self::get_by_username( $id );
}
/**
* Normalize a host.
*
* @param string $host The host.
*
* @return string The normalized host.
*/
public static function normalize_host( $host ) {
return \str_replace( 'www.', '', $host );
}
/**
* Normalize a URL.
*
* @param string $url The URL.
*
* @return string The normalized URL.
*/
public static function normalize_url( $url ) {
$url = \untrailingslashit( $url );
$url = \str_replace( 'https://', '', $url );
$url = \str_replace( 'http://', '', $url );
$url = \str_replace( 'www.', '', $url );
return $url;
}
/**
* Get the User collection.
*

View File

@ -1,6 +1,7 @@
<?php
namespace Activitypub;
use WP_Query;
use WP_Error;
use Activitypub\Http;
use Activitypub\Comment;
@ -794,6 +795,7 @@ function is_local_comment( $comment ) {
* Mark a WordPress object as federated.
*
* @param WP_Comment|WP_Post|mixed $wp_object
*
* @return void
*/
function set_wp_object_state( $wp_object, $state ) {
@ -808,6 +810,25 @@ function set_wp_object_state( $wp_object, $state ) {
}
}
/**
* Get the federation state of a WordPress object.
*
* @param WP_Comment|WP_Post|mixed $wp_object
*
* @return string|false The state of the object or false if not found.
*/
function get_wp_object_state( $wp_object ) {
$meta_key = 'activitypub_status';
if ( $wp_object instanceof \WP_Post ) {
return \get_post_meta( $wp_object->ID, $meta_key, true );
} elseif ( $wp_object instanceof \WP_Comment ) {
return \get_comment_meta( $wp_object->comment_ID, $meta_key, true );
} else {
return \apply_filters( 'activitypub_get_wp_object_state', false, $wp_object );
}
}
/**
* Get the description of a post type.
*
@ -969,3 +990,56 @@ function custom_large_numbers( $formatted, $number, $decimals ) {
// Default fallback. We should not get here.
return $formatted;
}
/**
* Normalize a URL.
*
* @param string $url The URL.
*
* @return string The normalized URL.
*/
function normalize_url( $url ) {
$url = \untrailingslashit( $url );
$url = \str_replace( 'https://', '', $url );
$url = \str_replace( 'http://', '', $url );
$url = \str_replace( 'www.', '', $url );
return $url;
}
/**
* Normalize a host.
*
* @param string $host The host.
*
* @return string The normalized host.
*/
function normalize_host( $host ) {
return \str_replace( 'www.', '', $host );
}
/**
* Get the Extra Fields of an Actor
*
* @param int $user_id The User-ID.
*
* @return array The extra fields.
*/
function get_actor_extra_fields( $user_id ) {
$extra_fields = new WP_Query(
array(
'post_type' => 'ap_extrafield',
'nopaging' => true,
'status' => 'publish',
'author' => $user_id,
)
);
if ( $extra_fields->have_posts() ) {
$extra_fields = $extra_fields->posts;
} else {
$extra_fields = array();
}
return apply_filters( 'activitypub_get_actor_extra_fields', $extra_fields, $user_id );
}

View File

@ -61,7 +61,7 @@ class Create {
$state = Interactions::add_comment( $array );
$reaction = null;
if ( $state && ! \is_wp_error( $reaction ) ) {
if ( $state && ! \is_wp_error( $state ) ) {
$reaction = \get_comment( $state );
}

View File

@ -197,4 +197,8 @@ class Application extends Actor {
)
);
}
public function get_canonical_url() {
return \home_url();
}
}

View File

@ -230,7 +230,7 @@ class Blog extends Actor {
*
* @return array|null The User-Header-Image.
*/
public function get_header_image() {
public function get_image() {
if ( \has_header_image() ) {
return array(
'type' => 'Image',
@ -368,4 +368,38 @@ class Blog extends Actor {
return false;
}
}
/**
* Extend the User-Output with Attachments.
*
* @return array The extended User-Output.
*/
public function get_attachment() {
$array = array();
$array[] = array(
'type' => 'PropertyValue',
'name' => \__( 'Blog', 'activitypub' ),
'value' => \html_entity_decode(
sprintf(
'<a rel="me" title="%s" target="_blank" href="%s">%s</a>',
\esc_attr( \home_url( '/' ) ),
\esc_url( \home_url( '/' ) ),
\wp_parse_url( \home_url( '/' ), \PHP_URL_HOST )
),
\ENT_QUOTES,
'UTF-8'
),
);
// Add support for FEP-fb2a, for more information see FEDERATION.md
$array[] = array(
'type' => 'Link',
'name' => \__( 'Blog', 'activitypub' ),
'href' => \esc_url( \home_url( '/' ) ),
'rel' => array( 'me' ),
);
return $array;
}
}

View File

@ -3,6 +3,7 @@ namespace Activitypub\Model;
use WP_Query;
use WP_Error;
use Activitypub\Migration;
use Activitypub\Signature;
use Activitypub\Model\Blog;
use Activitypub\Activity\Actor;
@ -10,6 +11,7 @@ use Activitypub\Collection\Users;
use function Activitypub\is_user_disabled;
use function Activitypub\get_rest_url_by_path;
use function Activitypub\get_actor_extra_fields;
class User extends Actor {
/**
@ -233,41 +235,74 @@ class User extends Actor {
* @return array The extended User-Output.
*/
public function get_attachment() {
$array = array();
$extra_fields = get_actor_extra_fields( $this->_id );
$array[] = array(
'type' => 'PropertyValue',
'name' => \__( 'Blog', 'activitypub' ),
'value' => \html_entity_decode(
'<a rel="me" title="' . \esc_attr( \home_url( '/' ) ) . '" target="_blank" href="' . \home_url( '/' ) . '">' . \wp_parse_url( \home_url( '/' ), \PHP_URL_HOST ) . '</a>',
\ENT_QUOTES,
'UTF-8'
),
);
$attachments = array();
$array[] = array(
'type' => 'PropertyValue',
'name' => \__( 'Profile', 'activitypub' ),
'value' => \html_entity_decode(
'<a rel="me" title="' . \esc_attr( \get_author_posts_url( $this->get__id() ) ) . '" target="_blank" href="' . \get_author_posts_url( $this->get__id() ) . '">' . \wp_parse_url( \get_author_posts_url( $this->get__id() ), \PHP_URL_HOST ) . '</a>',
\ENT_QUOTES,
'UTF-8'
),
);
foreach ( $extra_fields as $post ) {
$content = \get_the_content( null, false, $post );
$content = \make_clickable( $content );
$content = \do_blocks( $content );
$content = \wptexturize( $content );
$content = \wp_filter_content_tags( $content );
// replace script and style elements
$content = \preg_replace( '@<(script|style)[^>]*?>.*?</\\1>@si', '', $content );
$content = \strip_shortcodes( $content );
$content = \trim( \preg_replace( '/[\n\r\t]/', '', $content ) );
if ( \get_the_author_meta( 'user_url', $this->get__id() ) ) {
$array[] = array(
$attachments[] = array(
'type' => 'PropertyValue',
'name' => \__( 'Website', 'activitypub' ),
'name' => \get_the_title( $post ),
'value' => \html_entity_decode(
'<a rel="me" title="' . \esc_attr( \get_the_author_meta( 'user_url', $this->get__id() ) ) . '" target="_blank" href="' . \get_the_author_meta( 'user_url', $this->get__id() ) . '">' . \wp_parse_url( \get_the_author_meta( 'user_url', $this->get__id() ), \PHP_URL_HOST ) . '</a>',
$content,
\ENT_QUOTES,
'UTF-8'
),
);
$link_added = false;
// Add support for FEP-fb2a, for more information see FEDERATION.md
if ( \class_exists( '\WP_HTML_Tag_Processor' ) ) {
$tags = new \WP_HTML_Tag_Processor( $content );
$tags->next_tag();
if ( 'P' === $tags->get_tag() ) {
$tags->next_tag();
}
if ( 'A' === $tags->get_tag() ) {
$tags->set_bookmark( 'link' );
if ( ! $tags->next_tag() ) {
$tags->seek( 'link' );
$attachment = array(
'type' => 'Link',
'name' => \get_the_title( $post ),
'href' => \esc_url( $tags->get_attribute( 'href' ) ),
'rel' => explode( ' ', $tags->get_attribute( 'rel' ) ),
);
$link_added = true;
}
}
}
if ( ! $link_added ) {
$attachment = array(
'type' => 'Note',
'name' => \get_the_title( $post ),
'content' => \html_entity_decode(
$content,
\ENT_QUOTES,
'UTF-8'
),
);
}
$attachments[] = $attachment;
}
return $array;
return $attachments;
}
/**

View File

@ -123,7 +123,7 @@ class Actors {
$url = str_replace( '{uri}', $resource, $template );
return new WP_REST_Response(
array( 'url' => $url ),
array( 'url' => $url, 'template' => $template ),
200
);
}

View File

@ -29,7 +29,7 @@ class Comment {
public static function register_routes() {
\register_rest_route(
ACTIVITYPUB_REST_NAMESPACE,
'/(users|actors)/(?P<comment_id>\d+)/remote-reply',
'/comments/(?P<comment_id>\d+)/remote-reply',
array(
array(
'methods' => WP_REST_Server::READABLE,
@ -88,7 +88,7 @@ class Comment {
$url = str_replace( '{uri}', $resource, $template );
return new WP_REST_Response(
array( 'url' => $url ),
array( 'url' => $url, 'template' => $template ),
200
);
}

View File

@ -55,10 +55,28 @@ class Webfinger {
*/
\do_action( 'activitypub_rest_webfinger_pre' );
$code = 200;
$resource = $request->get_param( 'resource' );
$response = self::get_profile( $resource );
return new WP_REST_Response( $response, 200 );
if ( \is_wp_error( $response ) ) {
$code = 400;
$error_data = $response->get_error_data();
if ( isset( $error_data['status'] ) ) {
$code = $error_data['status'];
}
}
return new WP_REST_Response(
$response,
$code,
array(
'Access-Control-Allow-Origin' => '*',
'Content-Type' => 'application/jrd+json; charset=' . get_option( 'blog_charset' ),
)
);
}
/**
@ -88,7 +106,7 @@ class Webfinger {
public static function get_profile( $resource ) {
$user = User_Collection::get_by_resource( $resource );
if ( is_wp_error( $user ) ) {
if ( \is_wp_error( $user ) ) {
return $user;
}

View File

@ -101,6 +101,9 @@ class Post extends Base {
if ( 'trash' === get_post_status( $post ) ) {
$permalink = \get_post_meta( $post->ID, 'activitypub_canonical_url', true );
} elseif ( 'draft' === get_post_status( $post ) && get_sample_permalink( $post->ID ) ) {
$sample = get_sample_permalink( $post->ID );
$permalink = str_replace( array( '%pagename%', '%postname%' ), $sample[1], $sample[0] );
} else {
$permalink = \get_permalink( $post );
}
@ -137,6 +140,11 @@ class Post extends Base {
* @return array The Attachments.
*/
protected function get_attachment() {
// Remove attachments from drafts.
if ( 'draft' === \get_post_status( $this->wp_object ) ) {
return array();
}
// Once upon a time we only supported images, but we now support audio/video as well.
// We maintain the image-centric naming for backwards compatibility.
$max_media = \intval(
@ -692,6 +700,11 @@ class Post extends Base {
return null;
}
// Remove Teaser from drafts.
if ( 'draft' === \get_post_status( $this->wp_object ) ) {
return \__( '(This post is being modified)', 'activitypub' );
}
$content = \get_post_field( 'post_content', $this->wp_object->ID );
$content = \html_entity_decode( $content );
$content = \wp_strip_all_tags( $content );
@ -746,6 +759,11 @@ class Post extends Base {
* @return string The content.
*/
protected function get_content() {
// Remove Content from drafts.
if ( 'draft' === \get_post_status( $this->wp_object ) ) {
return \__( '(This post is being modified)', 'activitypub' );
}
global $post;
/**