updated plugin ActivityPub version 5.8.0

This commit is contained in:
2025-04-29 21:19:06 +00:00
committed by Gitium
parent 19dfd317cc
commit fdfbf76539
166 changed files with 14119 additions and 7163 deletions

View File

@ -7,8 +7,8 @@
namespace Activitypub;
use Activitypub\Collection\Actors;
use Activitypub\Collection\Followers;
use Activitypub\Collection\Users as User_Collection;
/**
* Block class.
@ -21,12 +21,14 @@ class Blocks {
// This is already being called on the init hook, so just add it.
self::register_blocks();
\add_action( 'wp_enqueue_scripts', array( self::class, 'add_data' ) );
\add_action( 'enqueue_block_editor_assets', array( self::class, 'add_data' ) );
\add_action( 'wp_head', array( self::class, 'inject_activitypub_options' ), 11 );
\add_action( 'admin_print_scripts', array( self::class, 'inject_activitypub_options' ) );
\add_action( 'load-post-new.php', array( self::class, 'handle_in_reply_to_get_param' ) );
// Add editor plugin.
\add_action( 'enqueue_block_editor_assets', array( self::class, 'enqueue_editor_assets' ) );
\add_action( 'init', array( self::class, 'register_postmeta' ), 11 );
\add_filter( 'activitypub_import_mastodon_post_data', array( self::class, 'filter_import_mastodon_post_data' ), 10, 2 );
}
/**
@ -42,7 +44,36 @@ class Blocks {
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'sanitize_callback' => function ( $warning ) {
if ( $warning ) {
return \sanitize_text_field( $warning );
}
return null;
},
)
);
\register_post_meta(
$post_type,
'activitypub_content_visibility',
array(
'type' => 'string',
'single' => true,
'show_in_rest' => true,
'sanitize_callback' => function ( $value ) {
$schema = array(
'type' => 'string',
'enum' => array( ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC, ACTIVITYPUB_CONTENT_VISIBILITY_QUIET_PUBLIC, ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE, ACTIVITYPUB_CONTENT_VISIBILITY_LOCAL ),
'default' => ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC,
);
if ( is_wp_error( rest_validate_enum( $value, $schema, '' ) ) ) {
return $schema['default'];
}
return $value;
},
)
);
}
@ -79,22 +110,22 @@ class Blocks {
}
/**
* Add data to the block editor.
* Output ActivityPub options as a script tag.
*/
public static function add_data() {
$context = is_admin() ? 'editor' : 'view';
$followers_handle = 'activitypub-followers-' . $context . '-script';
$follow_me_handle = 'activitypub-follow-me-' . $context . '-script';
$data = array(
'namespace' => ACTIVITYPUB_REST_NAMESPACE,
'enabled' => array(
public static function inject_activitypub_options() {
$data = array(
'namespace' => ACTIVITYPUB_REST_NAMESPACE,
'defaultAvatarUrl' => ACTIVITYPUB_PLUGIN_URL . 'assets/img/mp.jpg',
'enabled' => array(
'site' => ! is_user_type_disabled( 'blog' ),
'users' => ! is_user_type_disabled( 'user' ),
),
);
$js = sprintf( 'var _activityPubOptions = %s;', wp_json_encode( $data ) );
\wp_add_inline_script( $followers_handle, $js, 'before' );
\wp_add_inline_script( $follow_me_handle, $js, 'before' );
printf(
"\n<script>var _activityPubOptions = %s;</script>",
wp_json_encode( $data )
);
}
/**
@ -119,6 +150,38 @@ class Blocks {
'render_callback' => array( self::class, 'render_reply_block' ),
)
);
\register_block_type_from_metadata(
ACTIVITYPUB_PLUGIN_DIR . '/build/reactions',
array(
'render_callback' => array( self::class, 'render_post_reactions_block' ),
)
);
}
/**
* Render the post reactions block.
*
* @param array $attrs The block attributes.
*
* @return string The HTML to render.
*/
public static function render_post_reactions_block( $attrs ) {
if ( ! isset( $attrs['postId'] ) ) {
$attrs['postId'] = get_the_ID();
}
$wrapper_attributes = get_block_wrapper_attributes(
array(
'class' => 'activitypub-reactions-block',
'data-attrs' => wp_json_encode( $attrs ),
)
);
return sprintf(
'<div %s></div>',
$wrapper_attributes
);
}
/**
@ -134,7 +197,7 @@ class Blocks {
// If the user string is 'site', return the Blog User ID.
if ( 'site' === $user_string ) {
return User_Collection::BLOG_USER_ID;
return Actors::BLOG_USER_ID;
}
// The only other value should be 'inherit', which means to use the query context to determine the User.
@ -144,7 +207,7 @@ class Blocks {
// For a homepage/front page, if the Blog User is active, use it.
if ( ( is_front_page() || is_home() ) && ! is_user_type_disabled( 'blog' ) ) {
return User_Collection::BLOG_USER_ID;
return Actors::BLOG_USER_ID;
}
// If we're in a loop, use the post author.
@ -192,7 +255,7 @@ class Blocks {
*/
public static function render_follow_me_block( $attrs ) {
$user_id = self::get_user_id( $attrs['selectedUser'] );
$user = User_Collection::get_by_id( $user_id );
$user = Actors::get_by_id( $user_id );
if ( is_wp_error( $user ) ) {
if ( 'inherit' === $attrs['selectedUser'] ) {
// If the user is 'inherit' and we couldn't determine the user, don't render anything.
@ -210,7 +273,6 @@ class Blocks {
$wrapper_attributes = get_block_wrapper_attributes(
array(
'aria-label' => __( 'Follow me on the Fediverse', 'activitypub' ),
'class' => 'activitypub-follow-me-block-wrapper',
'data-attrs' => wp_json_encode( $attrs ),
)
@ -232,7 +294,7 @@ class Blocks {
return '<!-- Followers block: `inherit` mode does not display on this type of page -->';
}
$user = User_Collection::get_by_id( $followee_user_id );
$user = Actors::get_by_id( $followee_user_id );
if ( is_wp_error( $user ) ) {
return '<!-- Followers block: `' . $followee_user_id . '` not an active ActivityPub user -->';
}
@ -279,23 +341,45 @@ class Blocks {
* @return string The HTML to render.
*/
public static function render_reply_block( $attrs ) {
/**
* Filter the reply block.
*
* @param string $html The HTML to render.
* @param array $attrs The block attributes.
*/
return apply_filters(
'activitypub_reply_block',
sprintf(
// Return early if no URL is provided.
if ( empty( $attrs['url'] ) ) {
return null;
}
$show_embed = isset( $attrs['embedPost'] ) && $attrs['embedPost'];
$wrapper_attrs = get_block_wrapper_attributes(
array(
'aria-label' => __( 'Reply', 'activitypub' ),
'class' => 'activitypub-reply-block',
'data-in-reply-to' => $attrs['url'],
)
);
$html = '<div ' . $wrapper_attrs . '>';
// Try to get and append the embed if requested.
if ( $show_embed ) {
$embed = wp_oembed_get( $attrs['url'] );
if ( $embed ) {
$html .= $embed;
}
}
// Only show the link if we're not showing the embed.
if ( ! $show_embed ) {
$html .= sprintf(
'<p><a title="%2$s" aria-label="%2$s" href="%1$s" class="u-in-reply-to" target="_blank">%3$s</a></p>',
esc_url( $attrs['url'] ),
esc_attr__( 'This post is a response to the referenced content.', 'activitypub' ),
// translators: %s is the URL of the post being replied to.
sprintf( __( '&#8620;%s', 'activitypub' ), \str_replace( array( 'https://', 'http://' ), '', $attrs['url'] ) )
),
$attrs
);
sprintf( __( '&#8620;%s', 'activitypub' ), \str_replace( array( 'https://', 'http://' ), '', esc_url( $attrs['url'] ) ) )
);
}
$html .= '</div>';
return $html;
}
/**
@ -330,4 +414,33 @@ class Blocks {
$external_svg
);
}
/**
* Converts content to blocks before saving to the database.
*
* @param array $data The post data to be inserted.
* @param object $post The Mastodon Create activity.
*
* @return array
*/
public static function filter_import_mastodon_post_data( $data, $post ) {
// Convert paragraphs to blocks.
\preg_match_all( '#<p>.*?</p>#is', $data['post_content'], $matches );
$blocks = \array_map(
function ( $paragraph ) {
return '<!-- wp:paragraph -->' . PHP_EOL . $paragraph . PHP_EOL . '<!-- /wp:paragraph -->' . PHP_EOL;
},
$matches[0] ?? array()
);
$data['post_content'] = \rtrim( \implode( PHP_EOL, $blocks ), PHP_EOL );
// Add reply block if it's a reply.
if ( null !== $post->object->inReplyTo ) {
$reply_block = \sprintf( '<!-- wp:activitypub/reply {"url":"%1$s","embedPost":true} /-->' . PHP_EOL, \esc_url( $post->object->inReplyTo ) );
$data['post_content'] = $reply_block . $data['post_content'];
}
return $data;
}
}