updated plugin ActivityPub
version 2.4.0
This commit is contained in:
@ -3,13 +3,13 @@ namespace Activitypub\Transformer;
|
||||
|
||||
use WP_Post;
|
||||
use Activitypub\Shortcodes;
|
||||
use Activitypub\Model\Blog_User;
|
||||
use Activitypub\Model\Blog;
|
||||
use Activitypub\Transformer\Base;
|
||||
use Activitypub\Collection\Users;
|
||||
use Activitypub\Activity\Base_Object;
|
||||
|
||||
use function Activitypub\esc_hashtag;
|
||||
use function Activitypub\is_single_user;
|
||||
use function Activitypub\get_enclosures;
|
||||
use function Activitypub\get_rest_url_by_path;
|
||||
use function Activitypub\site_supports_blocks;
|
||||
|
||||
@ -70,7 +70,7 @@ class Post extends Base {
|
||||
$this->get_locale() => $this->get_content(),
|
||||
)
|
||||
);
|
||||
$path = sprintf( 'users/%d/followers', intval( $post->post_author ) );
|
||||
$path = sprintf( 'actors/%d/followers', intval( $post->post_author ) );
|
||||
|
||||
$object->set_to(
|
||||
array(
|
||||
@ -116,7 +116,7 @@ class Post extends Base {
|
||||
* @return string The User-URL.
|
||||
*/
|
||||
protected function get_attributed_to() {
|
||||
$blog_user = new Blog_User();
|
||||
$blog_user = new Blog();
|
||||
|
||||
if ( is_single_user() ) {
|
||||
return $blog_user->get_url();
|
||||
@ -139,14 +139,34 @@ class Post extends Base {
|
||||
protected function get_attachment() {
|
||||
// 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( \apply_filters( 'activitypub_max_image_attachments', \get_option( 'activitypub_max_image_attachments', ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS ) ) );
|
||||
$max_media = \intval(
|
||||
\apply_filters(
|
||||
'activitypub_max_image_attachments',
|
||||
\get_option( 'activitypub_max_image_attachments', ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS )
|
||||
)
|
||||
);
|
||||
|
||||
if ( site_supports_blocks() && \has_blocks( $this->wp_object->post_content ) ) {
|
||||
$media = $this->get_block_attachments( $max_media );
|
||||
} else {
|
||||
$media = $this->get_classic_editor_images( $max_media );
|
||||
$media = array(
|
||||
'audio' => array(),
|
||||
'video' => array(),
|
||||
'image' => array(),
|
||||
);
|
||||
$id = $this->wp_object->ID;
|
||||
|
||||
// list post thumbnail first if this post has one
|
||||
if ( \function_exists( 'has_post_thumbnail' ) && \has_post_thumbnail( $id ) ) {
|
||||
$media['image'][] = array( 'id' => \get_post_thumbnail_id( $id ) );
|
||||
}
|
||||
|
||||
$media = $this->get_enclosures( $media );
|
||||
|
||||
if ( site_supports_blocks() && \has_blocks( $this->wp_object->post_content ) ) {
|
||||
$media = $this->get_block_attachments( $media, $max_media );
|
||||
} else {
|
||||
$media = $this->get_classic_editor_images( $media, $max_media );
|
||||
}
|
||||
|
||||
$media = self::filter_media_by_object_type( $media, \get_post_format( $this->wp_object ), $this->wp_object );
|
||||
$unique_ids = \array_unique( \array_column( $media, 'id' ) );
|
||||
$media = \array_intersect_key( $media, $unique_ids );
|
||||
$media = \array_slice( $media, 0, $max_media );
|
||||
@ -157,35 +177,21 @@ class Post extends Base {
|
||||
/**
|
||||
* Get media attachments from blocks. They will be formatted as ActivityPub attachments, not as WP attachments.
|
||||
*
|
||||
* @param int $max_media The maximum number of attachments to return.
|
||||
* @param array $media The media array grouped by type.
|
||||
* @param int $max_media The maximum number of attachments to return.
|
||||
*
|
||||
* @return array The attachments.
|
||||
*/
|
||||
protected function get_block_attachments( $max_media ) {
|
||||
protected function get_block_attachments( $media, $max_media ) {
|
||||
// max media can't be negative or zero
|
||||
if ( $max_media <= 0 ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$id = $this->wp_object->ID;
|
||||
$blocks = \parse_blocks( $this->wp_object->post_content );
|
||||
$media = self::get_media_from_blocks( $blocks, $media );
|
||||
|
||||
$media = array(
|
||||
'image' => array(),
|
||||
'audio' => array(),
|
||||
'video' => array(),
|
||||
);
|
||||
|
||||
// list post thumbnail first if this post has one
|
||||
if ( \function_exists( 'has_post_thumbnail' ) && \has_post_thumbnail( $id ) ) {
|
||||
$media['image'][] = array( 'id' => \get_post_thumbnail_id( $id ) );
|
||||
}
|
||||
|
||||
if ( $max_media > 0 ) {
|
||||
$blocks = \parse_blocks( $this->wp_object->post_content );
|
||||
$media = self::get_media_from_blocks( $blocks, $media );
|
||||
}
|
||||
|
||||
return self::filter_media_by_object_type( $media, \get_post_format( $this->wp_object ) );
|
||||
return $media;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,8 +208,9 @@ class Post extends Base {
|
||||
if ( $max_images <= 0 ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$images = array();
|
||||
$query = new \WP_Query(
|
||||
$query = new \WP_Query(
|
||||
array(
|
||||
'post_parent' => $this->wp_object->ID,
|
||||
'post_status' => 'inherit',
|
||||
@ -214,6 +221,7 @@ class Post extends Base {
|
||||
'posts_per_page' => $max_images,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $query->get_posts() as $attachment ) {
|
||||
if ( ! \in_array( $attachment->ID, $images, true ) ) {
|
||||
$images[] = array( 'id' => $attachment->ID );
|
||||
@ -249,7 +257,7 @@ class Post extends Base {
|
||||
// This linter warning is a false positive - we have to
|
||||
// re-count each time here as we modify $images.
|
||||
// phpcs:ignore Squiz.PHP.DisallowSizeFunctionsInLoops.Found
|
||||
while ( $tags->next_tag( 'img' ) && ( \count( $images ) < $max_images ) ) {
|
||||
while ( $tags->next_tag( 'img' ) && ( \count( $images ) <= $max_images ) ) {
|
||||
$src = $tags->get_attribute( 'src' );
|
||||
|
||||
// If the img source is in our uploads dir, get the
|
||||
@ -292,34 +300,68 @@ class Post extends Base {
|
||||
* Get post images from the classic editor.
|
||||
* Note that audio/video attachments are only supported in the block editor.
|
||||
*
|
||||
* @param int $max_images The maximum number of images to return.
|
||||
* @param array $media The media array grouped by type.
|
||||
* @param int $max_images The maximum number of images to return.
|
||||
*
|
||||
* @return array The attachments.
|
||||
*/
|
||||
protected function get_classic_editor_images( $max_images ) {
|
||||
protected function get_classic_editor_images( $media, $max_images ) {
|
||||
// max images can't be negative or zero
|
||||
if ( $max_images <= 0 ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$id = $this->wp_object->ID;
|
||||
|
||||
$images = array();
|
||||
|
||||
// list post thumbnail first if this post has one
|
||||
if ( \function_exists( 'has_post_thumbnail' ) && \has_post_thumbnail( $id ) ) {
|
||||
$images[] = \get_post_thumbnail_id( $id );
|
||||
}
|
||||
|
||||
if ( \count( $images ) < $max_images ) {
|
||||
if ( \count( $media['image'] ) <= $max_images ) {
|
||||
if ( \class_exists( '\WP_HTML_Tag_Processor' ) ) {
|
||||
$images = \array_merge( $images, $this->get_classic_editor_image_embeds( $max_images ) );
|
||||
$media['image'] = \array_merge( $media['image'], $this->get_classic_editor_image_embeds( $max_images ) );
|
||||
} else {
|
||||
$images = \array_merge( $images, $this->get_classic_editor_image_attachments( $max_images ) );
|
||||
$media['image'] = \array_merge( $media['image'], $this->get_classic_editor_image_attachments( $max_images ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $images;
|
||||
return $media;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enclosures for a post.
|
||||
*
|
||||
* @param array $media The media array grouped by type.
|
||||
*
|
||||
* @return array The media array extended with enclosures.
|
||||
*/
|
||||
public function get_enclosures( $media ) {
|
||||
$enclosures = get_enclosures( $this->wp_object->ID );
|
||||
|
||||
if ( ! $enclosures ) {
|
||||
return $media;
|
||||
}
|
||||
|
||||
foreach ( $enclosures as $enclosure ) {
|
||||
// check if URL is an attachment
|
||||
$attachment_id = \attachment_url_to_postid( $enclosure['url'] );
|
||||
if ( $attachment_id ) {
|
||||
$enclosure['id'] = $attachment_id;
|
||||
$enclosure['url'] = \wp_get_attachment_url( $attachment_id );
|
||||
$enclosure['mediaType'] = \get_post_mime_type( $attachment_id );
|
||||
}
|
||||
|
||||
$mime_type = $enclosure['mediaType'];
|
||||
$mime_type_parts = \explode( '/', $mime_type );
|
||||
|
||||
switch ( $mime_type_parts[0] ) {
|
||||
case 'image':
|
||||
$media['image'][] = $enclosure;
|
||||
break;
|
||||
case 'audio':
|
||||
$media['audio'][] = $enclosure;
|
||||
break;
|
||||
case 'video':
|
||||
$media['video'][] = $enclosure;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $media;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,7 +373,6 @@ class Post extends Base {
|
||||
* @return array The image IDs.
|
||||
*/
|
||||
protected static function get_media_from_blocks( $blocks, $media ) {
|
||||
|
||||
foreach ( $blocks as $block ) {
|
||||
// recurse into inner blocks
|
||||
if ( ! empty( $block['innerBlocks'] ) ) {
|
||||
@ -397,19 +438,19 @@ class Post extends Base {
|
||||
/**
|
||||
* Filter media IDs by object type.
|
||||
*
|
||||
* @param array $media The media array grouped by type.
|
||||
* @param array $type The object type.
|
||||
* @param array $media The media array grouped by type.
|
||||
* @param string $type The object type.
|
||||
*
|
||||
* @return array The filtered media IDs.
|
||||
*/
|
||||
protected static function filter_media_by_object_type( $media, $type ) {
|
||||
$type = \apply_filters( 'filter_media_by_object_type', \strtolower( $type ) );
|
||||
protected static function filter_media_by_object_type( $media, $type, $wp_object ) {
|
||||
$type = \apply_filters( 'filter_media_by_object_type', \strtolower( $type ), $wp_object );
|
||||
|
||||
if ( ! empty( $media[ $type ] ) ) {
|
||||
return $media[ $type ];
|
||||
}
|
||||
|
||||
return array_merge( array(), ...array_values( $media ) );
|
||||
return array_filter( array_merge( array(), ...array_values( $media ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -420,6 +461,10 @@ class Post extends Base {
|
||||
* @return array The ActivityPub Attachment.
|
||||
*/
|
||||
public static function wp_attachment_to_activity_attachment( $media ) {
|
||||
if ( ! isset( $media['id'] ) ) {
|
||||
return $media;
|
||||
}
|
||||
|
||||
$id = $media['id'];
|
||||
$attachment = array();
|
||||
$mime_type = \get_post_mime_type( $id );
|
||||
@ -427,14 +472,14 @@ class Post extends Base {
|
||||
// switching on image/audio/video
|
||||
switch ( $mime_type_parts[0] ) {
|
||||
case 'image':
|
||||
$image_size = 'full';
|
||||
$image_size = 'large';
|
||||
|
||||
/**
|
||||
* Filter the image URL returned for each post.
|
||||
*
|
||||
* @param array|false $thumbnail The image URL, or false if no image is available.
|
||||
* @param int $id The attachment ID.
|
||||
* @param string $image_size The image size to retrieve. Set to 'full' by default.
|
||||
* @param string $image_size The image size to retrieve. Set to 'large' by default.
|
||||
*/
|
||||
$thumbnail = apply_filters(
|
||||
'activitypub_get_image',
|
||||
@ -488,16 +533,16 @@ class Post extends Base {
|
||||
* Return details about an image attachment.
|
||||
*
|
||||
* @param int $id The attachment ID.
|
||||
* @param string $image_size The image size to retrieve. Set to 'full' by default.
|
||||
* @param string $image_size The image size to retrieve. Set to 'large' by default.
|
||||
*
|
||||
* @return array|false Array of image data, or boolean false if no image is available.
|
||||
*/
|
||||
protected static function get_wordpress_attachment( $id, $image_size = 'full' ) {
|
||||
protected static function get_wordpress_attachment( $id, $image_size = 'large' ) {
|
||||
/**
|
||||
* Hook into the image retrieval process. Before image retrieval.
|
||||
*
|
||||
* @param int $id The attachment ID.
|
||||
* @param string $image_size The image size to retrieve. Set to 'full' by default.
|
||||
* @param string $image_size The image size to retrieve. Set to 'large' by default.
|
||||
*/
|
||||
do_action( 'activitypub_get_image_pre', $id, $image_size );
|
||||
|
||||
@ -507,7 +552,7 @@ class Post extends Base {
|
||||
* Hook into the image retrieval process. After image retrieval.
|
||||
*
|
||||
* @param int $id The attachment ID.
|
||||
* @param string $image_size The image size to retrieve. Set to 'full' by default.
|
||||
* @param string $image_size The image size to retrieve. Set to 'large' by default.
|
||||
*/
|
||||
do_action( 'activitypub_get_image_post', $id, $image_size );
|
||||
|
||||
@ -536,7 +581,7 @@ class Post extends Base {
|
||||
}
|
||||
|
||||
// Default to Article.
|
||||
$object_type = 'Article';
|
||||
$object_type = 'Note';
|
||||
$post_format = 'standard';
|
||||
|
||||
if ( \get_theme_support( 'post-formats' ) ) {
|
||||
@ -547,18 +592,12 @@ class Post extends Base {
|
||||
switch ( $post_type ) {
|
||||
case 'post':
|
||||
switch ( $post_format ) {
|
||||
case 'aside':
|
||||
case 'status':
|
||||
case 'quote':
|
||||
case 'note':
|
||||
case 'gallery':
|
||||
case 'image':
|
||||
case 'video':
|
||||
case 'audio':
|
||||
$object_type = 'Note';
|
||||
case 'standard':
|
||||
case '':
|
||||
$object_type = 'Article';
|
||||
break;
|
||||
default:
|
||||
$object_type = 'Article';
|
||||
$object_type = 'Note';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -566,7 +605,7 @@ class Post extends Base {
|
||||
$object_type = 'Page';
|
||||
break;
|
||||
default:
|
||||
$object_type = 'Article';
|
||||
$object_type = 'Note';
|
||||
break;
|
||||
}
|
||||
|
||||
@ -593,6 +632,16 @@ class Post extends Base {
|
||||
return $cc;
|
||||
}
|
||||
|
||||
|
||||
public function get_audience() {
|
||||
if ( is_single_user() ) {
|
||||
return null;
|
||||
} else {
|
||||
$blog = new Blog();
|
||||
return $blog->get_id();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of Tags, used in the Post.
|
||||
*
|
||||
@ -708,6 +757,8 @@ class Post extends Base {
|
||||
*/
|
||||
do_action( 'activitypub_before_get_content', $post );
|
||||
|
||||
add_filter( 'render_block_core/embed', array( self::class, 'revert_embed_links' ), 10, 2 );
|
||||
|
||||
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
$post = $this->wp_object;
|
||||
$content = $this->get_post_content_template();
|
||||
@ -792,4 +843,21 @@ class Post extends Base {
|
||||
*/
|
||||
return apply_filters( 'activitypub_post_locale', $lang, $post_id, $this->wp_object );
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform Embed blocks to block level link.
|
||||
*
|
||||
* Remote servers will simply drop iframe elements, rendering incomplete content.
|
||||
*
|
||||
* @see https://www.w3.org/TR/activitypub/#security-sanitizing-content
|
||||
* @see https://www.w3.org/wiki/ActivityPub/Primer/HTML
|
||||
*
|
||||
* @param string $block_content The block content (html)
|
||||
* @param object $block The block object
|
||||
*
|
||||
* @return string A block level link
|
||||
*/
|
||||
public static function revert_embed_links( $block_content, $block ) {
|
||||
return '<p><a href="' . esc_url( $block['attrs']['url'] ) . '">' . $block['attrs']['url'] . '</a></p>';
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user