updated plugin ActivityPub
version 2.0.1
This commit is contained in:
@ -2,10 +2,11 @@
|
||||
namespace Activitypub\Transformer;
|
||||
|
||||
use WP_Post;
|
||||
use Activitypub\Collection\Users;
|
||||
use Activitypub\Model\Blog_User;
|
||||
use Activitypub\Activity\Base_Object;
|
||||
use Activitypub\Shortcodes;
|
||||
use Activitypub\Model\Blog_User;
|
||||
use Activitypub\Transformer\Base;
|
||||
use Activitypub\Collection\Users;
|
||||
use Activitypub\Activity\Base_Object;
|
||||
|
||||
use function Activitypub\esc_hashtag;
|
||||
use function Activitypub\is_single_user;
|
||||
@ -15,42 +16,32 @@ use function Activitypub\site_supports_blocks;
|
||||
/**
|
||||
* WordPress Post Transformer
|
||||
*
|
||||
* The Post Transformer is responsible for transforming a WP_Post object into different othe
|
||||
* The Post Transformer is responsible for transforming a WP_Post object into different other
|
||||
* Object-Types.
|
||||
*
|
||||
* Currently supported are:
|
||||
*
|
||||
* - Activitypub\Activity\Base_Object
|
||||
*/
|
||||
class Post {
|
||||
|
||||
class Post extends Base {
|
||||
/**
|
||||
* The WP_Post object.
|
||||
* Returns the ID of the WordPress Post.
|
||||
*
|
||||
* @var WP_Post
|
||||
* @return int The ID of the WordPress Post
|
||||
*/
|
||||
protected $wp_post;
|
||||
|
||||
/**
|
||||
* Static function to Transform a WP_Post Object.
|
||||
*
|
||||
* This helps to chain the output of the Transformer.
|
||||
*
|
||||
* @param WP_Post $wp_post The WP_Post object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function transform( WP_Post $wp_post ) {
|
||||
return new static( $wp_post );
|
||||
public function get_wp_user_id() {
|
||||
return $this->wp_object->post_author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the User-ID of the WordPress Post.
|
||||
*
|
||||
*
|
||||
* @param WP_Post $wp_post
|
||||
* @return int The User-ID of the WordPress Post
|
||||
*/
|
||||
public function __construct( WP_Post $wp_post ) {
|
||||
$this->wp_post = $wp_post;
|
||||
public function change_wp_user_id( $user_id ) {
|
||||
$this->wp_object->post_author = $user_id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,31 +52,25 @@ class Post {
|
||||
* @return \Activitypub\Activity\Base_Object The ActivityPub Object
|
||||
*/
|
||||
public function to_object() {
|
||||
$wp_post = $this->wp_post;
|
||||
$object = new Base_Object();
|
||||
$post = $this->wp_object;
|
||||
$object = parent::to_object();
|
||||
|
||||
$object->set_id( $this->get_id() );
|
||||
$object->set_url( $this->get_url() );
|
||||
$object->set_type( $this->get_object_type() );
|
||||
|
||||
$published = \strtotime( $wp_post->post_date_gmt );
|
||||
$published = \strtotime( $post->post_date_gmt );
|
||||
|
||||
$object->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', $published ) );
|
||||
|
||||
$updated = \strtotime( $wp_post->post_modified_gmt );
|
||||
$updated = \strtotime( $post->post_modified_gmt );
|
||||
|
||||
if ( $updated > $published ) {
|
||||
$object->set_updated( \gmdate( 'Y-m-d\TH:i:s\Z', $updated ) );
|
||||
}
|
||||
|
||||
$object->set_attributed_to( $this->get_attributed_to() );
|
||||
$object->set_content( $this->get_content() );
|
||||
$object->set_content_map(
|
||||
array(
|
||||
$this->get_locale() => $this->get_content(),
|
||||
)
|
||||
);
|
||||
$path = sprintf( 'users/%d/followers', intval( $wp_post->post_author ) );
|
||||
$path = sprintf( 'users/%d/followers', intval( $post->post_author ) );
|
||||
|
||||
$object->set_to(
|
||||
array(
|
||||
@ -93,9 +78,6 @@ class Post {
|
||||
get_rest_url_by_path( $path ),
|
||||
)
|
||||
);
|
||||
$object->set_cc( $this->get_cc() );
|
||||
$object->set_attachment( $this->get_attachments() );
|
||||
$object->set_tag( $this->get_tags() );
|
||||
|
||||
return $object;
|
||||
}
|
||||
@ -115,7 +97,7 @@ class Post {
|
||||
* @return string The Posts URL.
|
||||
*/
|
||||
public function get_url() {
|
||||
$post = $this->wp_post;
|
||||
$post = $this->wp_object;
|
||||
|
||||
if ( 'trash' === get_post_status( $post ) ) {
|
||||
$permalink = \get_post_meta( $post->ID, 'activitypub_canonical_url', true );
|
||||
@ -134,12 +116,19 @@ class Post {
|
||||
* @return string The User-URL.
|
||||
*/
|
||||
protected function get_attributed_to() {
|
||||
$blog_user = new Blog_User();
|
||||
|
||||
if ( is_single_user() ) {
|
||||
$user = new Blog_User();
|
||||
return $blog_user->get_url();
|
||||
}
|
||||
|
||||
$user = Users::get_by_id( $this->wp_object->post_author );
|
||||
|
||||
if ( $user && ! is_wp_error( $user ) ) {
|
||||
return $user->get_url();
|
||||
}
|
||||
|
||||
return Users::get_by_id( $this->wp_post->post_author )->get_url();
|
||||
return $blog_user->get_url();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,12 +136,12 @@ class Post {
|
||||
*
|
||||
* @return array The Attachments.
|
||||
*/
|
||||
protected function get_attachments() {
|
||||
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 ) ) );
|
||||
|
||||
if ( site_supports_blocks() && \has_blocks( $this->wp_post->post_content ) ) {
|
||||
if ( site_supports_blocks() && \has_blocks( $this->wp_object->post_content ) ) {
|
||||
return $this->get_block_attachments( $max_media );
|
||||
}
|
||||
|
||||
@ -172,7 +161,7 @@ class Post {
|
||||
return array();
|
||||
}
|
||||
|
||||
$id = $this->wp_post->ID;
|
||||
$id = $this->wp_object->ID;
|
||||
|
||||
$media_ids = array();
|
||||
|
||||
@ -182,7 +171,7 @@ class Post {
|
||||
}
|
||||
|
||||
if ( $max_media > 0 ) {
|
||||
$blocks = \parse_blocks( $this->wp_post->post_content );
|
||||
$blocks = \parse_blocks( $this->wp_object->post_content );
|
||||
$media_ids = self::get_media_ids_from_blocks( $blocks, $media_ids, $max_media );
|
||||
}
|
||||
|
||||
@ -191,6 +180,103 @@ class Post {
|
||||
|
||||
/**
|
||||
* Get image attachments from the classic editor.
|
||||
* This is imperfect as the contained images aren't necessarily the
|
||||
* same as the attachments.
|
||||
*
|
||||
* @param int $max_images The maximum number of images to return.
|
||||
*
|
||||
* @return array The attachment IDs.
|
||||
*/
|
||||
protected function get_classic_editor_image_attachments( $max_images ) {
|
||||
// max images can't be negative or zero
|
||||
if ( $max_images <= 0 ) {
|
||||
return array();
|
||||
}
|
||||
$image_ids = array();
|
||||
$query = new \WP_Query(
|
||||
array(
|
||||
'post_parent' => $this->wp_object->ID,
|
||||
'post_status' => 'inherit',
|
||||
'post_type' => 'attachment',
|
||||
'post_mime_type' => 'image',
|
||||
'order' => 'ASC',
|
||||
'orderby' => 'menu_order ID',
|
||||
'posts_per_page' => $max_images,
|
||||
)
|
||||
);
|
||||
foreach ( $query->get_posts() as $attachment ) {
|
||||
if ( ! \in_array( $attachment->ID, $image_ids, true ) ) {
|
||||
$image_ids[] = $attachment->ID;
|
||||
}
|
||||
}
|
||||
return $image_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get image embeds from the classic editor by parsing HTML.
|
||||
*
|
||||
* @param int $max_images The maximum number of images to return.
|
||||
*
|
||||
* @return array The attachment IDs.
|
||||
*/
|
||||
protected function get_classic_editor_image_embeds( $max_images ) {
|
||||
// if someone calls that function directly, bail
|
||||
if ( ! \class_exists( '\WP_HTML_Tag_Processor' ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// max images can't be negative or zero
|
||||
if ( $max_images <= 0 ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$image_ids = array();
|
||||
$base = \wp_get_upload_dir()['baseurl'];
|
||||
$content = \get_post_field( 'post_content', $this->wp_object );
|
||||
$tags = new \WP_HTML_Tag_Processor( $content );
|
||||
|
||||
// This linter warning is a false positive - we have to
|
||||
// re-count each time here as we modify $image_ids.
|
||||
// phpcs:ignore Squiz.PHP.DisallowSizeFunctionsInLoops.Found
|
||||
while ( $tags->next_tag( 'img' ) && ( \count( $image_ids ) < $max_images ) ) {
|
||||
$src = $tags->get_attribute( 'src' );
|
||||
|
||||
// If the img source is in our uploads dir, get the
|
||||
// associated ID. Note: if there's a -500x500
|
||||
// type suffix, we remove it, but we try the original
|
||||
// first in case the original image is actually called
|
||||
// that. Likewise, we try adding the -scaled suffix for
|
||||
// the case that this is a small version of an image
|
||||
// that was big enough to get scaled down on upload:
|
||||
// https://make.wordpress.org/core/2019/10/09/introducing-handling-of-big-images-in-wordpress-5-3/
|
||||
if ( null !== $src && \str_starts_with( $src, $base ) ) {
|
||||
$img_id = \attachment_url_to_postid( $src );
|
||||
|
||||
if ( 0 === $img_id ) {
|
||||
$count = 0;
|
||||
$src = preg_replace( '/-(?:\d+x\d+)(\.[a-zA-Z]+)$/', '$1', $src, 1, $count );
|
||||
if ( $count > 0 ) {
|
||||
$img_id = \attachment_url_to_postid( $src );
|
||||
}
|
||||
}
|
||||
|
||||
if ( 0 === $img_id ) {
|
||||
$src = preg_replace( '/(\.[a-zA-Z]+)$/', '-scaled$1', $src );
|
||||
$img_id = \attachment_url_to_postid( $src );
|
||||
}
|
||||
|
||||
if ( 0 !== $img_id ) {
|
||||
if ( ! \in_array( $img_id, $image_ids, true ) ) {
|
||||
$image_ids[] = $img_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $image_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -203,35 +289,24 @@ class Post {
|
||||
return array();
|
||||
}
|
||||
|
||||
$id = $this->wp_post->ID;
|
||||
$id = $this->wp_object->ID;
|
||||
|
||||
$image_ids = array();
|
||||
|
||||
// list post thumbnail first if this post has one
|
||||
if ( \function_exists( 'has_post_thumbnail' ) && \has_post_thumbnail( $id ) ) {
|
||||
$image_ids[] = \get_post_thumbnail_id( $id );
|
||||
--$max_images;
|
||||
}
|
||||
|
||||
if ( $max_images > 0 ) {
|
||||
$query = new \WP_Query(
|
||||
array(
|
||||
'post_parent' => $id,
|
||||
'post_status' => 'inherit',
|
||||
'post_type' => 'attachment',
|
||||
'post_mime_type' => 'image',
|
||||
'order' => 'ASC',
|
||||
'orderby' => 'menu_order ID',
|
||||
'posts_per_page' => $max_images,
|
||||
)
|
||||
);
|
||||
foreach ( $query->get_posts() as $attachment ) {
|
||||
if ( ! \in_array( $attachment->ID, $image_ids, true ) ) {
|
||||
$image_ids[] = $attachment->ID;
|
||||
}
|
||||
if ( \count( $image_ids ) < $max_images ) {
|
||||
if ( \class_exists( '\WP_HTML_Tag_Processor' ) ) {
|
||||
$image_ids = \array_merge( $image_ids, $this->get_classic_editor_image_embeds( $max_images ) );
|
||||
} else {
|
||||
$image_ids = \array_merge( $image_ids, $this->get_classic_editor_image_attachments( $max_images ) );
|
||||
}
|
||||
}
|
||||
$image_ids = \array_unique( $image_ids );
|
||||
// unique then slice as the thumbnail may duplicate another image
|
||||
$image_ids = \array_slice( \array_unique( $image_ids ), 0, $max_images );
|
||||
|
||||
return \array_filter( \array_map( array( self::class, 'wp_attachment_to_activity_attachment' ), $image_ids ) );
|
||||
}
|
||||
@ -316,7 +391,7 @@ class Post {
|
||||
*/
|
||||
$thumbnail = apply_filters(
|
||||
'activitypub_get_image',
|
||||
self::get_image( $id, $image_size ),
|
||||
self::get_wordpress_attachment( $id, $image_size ),
|
||||
$id,
|
||||
$image_size
|
||||
);
|
||||
@ -365,7 +440,7 @@ class Post {
|
||||
*
|
||||
* @return array|false Array of image data, or boolean false if no image is available.
|
||||
*/
|
||||
protected static function get_image( $id, $image_size = 'full' ) {
|
||||
protected static function get_wordpress_attachment( $id, $image_size = 'full' ) {
|
||||
/**
|
||||
* Hook into the image retrieval process. Before image retrieval.
|
||||
*
|
||||
@ -395,17 +470,17 @@ class Post {
|
||||
*
|
||||
* @return string The Object-Type.
|
||||
*/
|
||||
protected function get_object_type() {
|
||||
protected function get_type() {
|
||||
if ( 'wordpress-post-format' !== \get_option( 'activitypub_object_type', 'note' ) ) {
|
||||
return \ucfirst( \get_option( 'activitypub_object_type', 'note' ) );
|
||||
}
|
||||
|
||||
// Default to Article.
|
||||
$object_type = 'Article';
|
||||
$post_type = \get_post_type( $this->wp_post );
|
||||
$post_type = \get_post_type( $this->wp_object );
|
||||
switch ( $post_type ) {
|
||||
case 'post':
|
||||
$post_format = \get_post_format( $this->wp_post );
|
||||
$post_format = \get_post_format( $this->wp_object );
|
||||
switch ( $post_format ) {
|
||||
case 'aside':
|
||||
case 'status':
|
||||
@ -481,10 +556,10 @@ class Post {
|
||||
*
|
||||
* @return array The list of Tags.
|
||||
*/
|
||||
protected function get_tags() {
|
||||
protected function get_tag() {
|
||||
$tags = array();
|
||||
|
||||
$post_tags = \get_the_tags( $this->wp_post->ID );
|
||||
$post_tags = \get_the_tags( $this->wp_object->ID );
|
||||
if ( $post_tags ) {
|
||||
foreach ( $post_tags as $post_tag ) {
|
||||
$tag = array(
|
||||
@ -531,7 +606,7 @@ class Post {
|
||||
do_action( 'activitypub_before_get_content', $post );
|
||||
|
||||
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
$post = $this->wp_post;
|
||||
$post = $this->wp_object;
|
||||
$content = $this->get_post_content_template();
|
||||
|
||||
// Register our shortcodes just in time.
|
||||
@ -559,19 +634,24 @@ class Post {
|
||||
* @return string The Template.
|
||||
*/
|
||||
protected function get_post_content_template() {
|
||||
if ( 'excerpt' === \get_option( 'activitypub_post_content_type', 'content' ) ) {
|
||||
return "[ap_excerpt]\n\n[ap_permalink type=\"html\"]";
|
||||
$type = \get_option( 'activitypub_post_content_type', 'content' );
|
||||
|
||||
switch ( $type ) {
|
||||
case 'excerpt':
|
||||
$template = "[ap_excerpt]\n\n[ap_permalink type=\"html\"]";
|
||||
break;
|
||||
case 'title':
|
||||
$template = "[ap_title]\n\n[ap_permalink type=\"html\"]";
|
||||
break;
|
||||
case 'content':
|
||||
$template = "[ap_content]\n\n[ap_permalink type=\"html\"]\n\n[ap_hashtags]";
|
||||
break;
|
||||
default:
|
||||
$template = \get_option( 'activitypub_custom_post_content', ACTIVITYPUB_CUSTOM_POST_CONTENT );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( 'title' === \get_option( 'activitypub_post_content_type', 'content' ) ) {
|
||||
return "[ap_title]\n\n[ap_permalink type=\"html\"]";
|
||||
}
|
||||
|
||||
if ( 'content' === \get_option( 'activitypub_post_content_type', 'content' ) ) {
|
||||
return "[ap_content]\n\n[ap_permalink type=\"html\"]\n\n[ap_hashtags]";
|
||||
}
|
||||
|
||||
return \get_option( 'activitypub_custom_post_content', ACTIVITYPUB_CUSTOM_POST_CONTENT );
|
||||
return apply_filters( 'activitypub_object_content_template', $template, $this->wp_object );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -580,7 +660,7 @@ class Post {
|
||||
* @return array The list of @-Mentions.
|
||||
*/
|
||||
protected function get_mentions() {
|
||||
return apply_filters( 'activitypub_extract_mentions', array(), $this->wp_post->post_content, $this->wp_post );
|
||||
return apply_filters( 'activitypub_extract_mentions', array(), $this->wp_object->post_content, $this->wp_object );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -589,7 +669,7 @@ class Post {
|
||||
* @return string The locale of the post.
|
||||
*/
|
||||
public function get_locale() {
|
||||
$post_id = $this->wp_post->ID;
|
||||
$post_id = $this->wp_object->ID;
|
||||
$lang = \strtolower( \strtok( \get_locale(), '_-' ) );
|
||||
|
||||
/**
|
||||
@ -601,6 +681,6 @@ class Post {
|
||||
*
|
||||
* @return string The filtered locale of the post.
|
||||
*/
|
||||
return apply_filters( 'activitypub_post_locale', $lang, $post_id, $this->wp_post );
|
||||
return apply_filters( 'activitypub_post_locale', $lang, $post_id, $this->wp_object );
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user