updated plugin ActivityPub version 9.1.0

This commit is contained in:
2026-07-28 15:03:10 +00:00
committed by Gitium
parent bf428f0e45
commit ff806e1811
217 changed files with 6098 additions and 3025 deletions

View File

@ -66,7 +66,7 @@ class Activity_Object extends Base {
*
* @return array The filtered mentions.
*/
return apply_filters(
return \apply_filters(
'activitypub_extract_mentions',
array(),
$this->item->get_content() . ' ' . $this->item->get_summary(),
@ -145,7 +145,7 @@ class Activity_Object extends Base {
foreach ( $mentions as $mention => $url ) {
$tag = array(
'type' => 'Mention',
'href' => \esc_url( $url ),
'href' => \esc_url_raw( $url ),
'name' => \esc_html( $mention ),
);
$tags[] = $tag;

View File

@ -16,6 +16,10 @@ namespace Activitypub\Transformer;
* Currently supported are:
*
* - Activitypub\Activity\Base_Object
*
* Redaction is inherited from {@see Post::is_redacted()}: `is_post_publicly_queryable()`
* already resolves an attachment's own visibility, password, post-type support, and — for
* attached media — its parent's visibility, so no attachment-specific override is needed.
*/
class Attachment extends Post {
/**
@ -42,7 +46,7 @@ class Attachment extends Post {
$attachment = array(
'type' => $type,
'url' => wp_get_attachment_url( $this->item->ID ),
'url' => \wp_get_attachment_url( $this->item->ID ),
'mediaType' => $mime_type,
);

View File

@ -40,8 +40,6 @@ abstract class Base {
/**
* The WP_Post or WP_Comment object.
*
* @deprecated version 5.0.0
*
* @var \WP_Post|\WP_Comment
*/
protected $wp_object;
@ -187,7 +185,7 @@ abstract class Base {
$followers = $actor->get_followers();
}
$mentions = array_values( $this->get_mentions() );
$mentions = \array_values( $this->get_mentions() );
if ( $this->get_in_reply_to() ) {
$object = Http::get_remote_object( $this->get_in_reply_to() );
@ -280,7 +278,7 @@ abstract class Base {
*
* @return string The filtered locale of the post.
*/
return apply_filters( 'activitypub_locale', $lang, $this->item );
return \apply_filters( 'activitypub_locale', $lang, $this->item );
}
/**
@ -349,7 +347,7 @@ abstract class Base {
foreach ( $mentions as $mention => $url ) {
$tags[] = array(
'type' => 'Mention',
'href' => \esc_url( $url ),
'href' => \esc_url_raw( $url ),
'name' => \esc_html( $mention ),
);
}
@ -374,11 +372,11 @@ abstract class Base {
protected function get_mentions() {
$content = '';
if ( method_exists( $this, 'get_content' ) ) {
if ( \method_exists( $this, 'get_content' ) ) {
$content = $content . ' ' . $this->get_content();
}
if ( method_exists( $this, 'get_summary' ) ) {
if ( \method_exists( $this, 'get_summary' ) ) {
$content = $content . ' ' . $this->get_summary();
}
@ -391,7 +389,7 @@ abstract class Base {
*
* @return array The filtered mentions.
*/
return apply_filters(
return \apply_filters(
'activitypub_extract_mentions',
array(),
$content,
@ -530,7 +528,7 @@ abstract class Base {
if ( $thumbnail ) {
$image = array(
'type' => 'Image',
'url' => \esc_url( $thumbnail[0] ),
'url' => \esc_url_raw( $thumbnail[0] ),
'mediaType' => \esc_attr( $mime_type ),
);
@ -559,7 +557,7 @@ abstract class Base {
$attachment = array(
'type' => \ucfirst( $media_type ),
'mediaType' => \esc_attr( $mime_type ),
'url' => \esc_url( \wp_get_attachment_url( $id ) ),
'url' => \esc_url_raw( \wp_get_attachment_url( $id ) ),
'name' => \esc_attr( \get_the_title( $id ) ),
);
@ -725,7 +723,7 @@ abstract class Base {
return \array_filter(
$attachments,
static function ( $attachment ) use ( &$seen_ids ) {
if ( isset( $attachment['id'] ) && ! in_array( $attachment['id'], $seen_ids, true ) ) {
if ( isset( $attachment['id'] ) && ! \in_array( $attachment['id'], $seen_ids, true ) ) {
$seen_ids[] = $attachment['id'];
return true;
}

View File

@ -123,11 +123,11 @@ class Comment extends Base {
$mentions = '';
foreach ( $this->extract_reply_context() as $acct => $url ) {
$mentions .= sprintf(
$mentions .= \sprintf(
'<a rel="mention" class="u-url mention" href="%1$s" title="%2$s">%3$s</a> ',
esc_url( $url ),
esc_attr( $acct ),
esc_html( '@' . strtok( $acct, '@' ) )
\esc_url( $url ),
\esc_attr( $acct ),
\esc_html( '@' . \strtok( $acct, '@' ) )
);
}
$content = $mentions . $content;
@ -215,7 +215,7 @@ class Comment extends Base {
$user = Actors::get_by_id( $this->item->user_id );
if ( $user && ! is_wp_error( $user ) ) {
if ( $user && ! \is_wp_error( $user ) ) {
$this->actor_object = $user;
return $user;
}
@ -240,7 +240,7 @@ class Comment extends Base {
*
* @return array The filtered list of mentions.
*/
return apply_filters( 'activitypub_extract_mentions', array(), $this->item->comment_content, $this->item );
return \apply_filters( 'activitypub_extract_mentions', array(), $this->item->comment_content, $this->item );
}
/**
@ -252,7 +252,7 @@ class Comment extends Base {
$ancestors = get_comment_ancestors( $this->item );
// Now that we have the full tree of ancestors, only return the ones received from the fediverse.
return array_filter(
return \array_filter(
$ancestors,
static function ( $comment_id ) {
return \get_comment_meta( $comment_id, 'protocol', true ) === 'activitypub';
@ -270,7 +270,7 @@ class Comment extends Base {
*/
public function extract_reply_context( $mentions = array() ) {
// Check if `$this->item` is a WP_Comment.
if ( 'WP_Comment' !== get_class( $this->item ) ) {
if ( 'WP_Comment' !== \get_class( $this->item ) ) {
return $mentions;
}
@ -283,8 +283,8 @@ class Comment extends Base {
$comment = \get_comment( $comment_id );
if ( $comment && ! empty( $comment->comment_author_url ) ) {
$acct = Webfinger::uri_to_acct( $comment->comment_author_url );
if ( $acct && ! is_wp_error( $acct ) ) {
$acct = str_replace( 'acct:', '@', $acct );
if ( $acct && ! \is_wp_error( $acct ) ) {
$acct = \str_replace( 'acct:', '@', $acct );
$mentions[ $acct ] = $comment->comment_author_url;
}
}
@ -345,7 +345,7 @@ class Comment extends Base {
*/
protected function get_context() {
if ( $this->item->comment_post_ID ) {
return get_rest_url_by_path( sprintf( 'posts/%d/context', $this->item->comment_post_ID ) );
return get_rest_url_by_path( \sprintf( 'posts/%d/context', $this->item->comment_post_ID ) );
}
return null;

View File

@ -46,7 +46,7 @@ class Factory {
} elseif ( \is_object( $data ) ) {
$class = \get_class( $data );
} else {
return new \WP_Error( 'invalid_object', __( 'Invalid object', 'activitypub' ) );
return new \WP_Error( 'invalid_object', \__( 'Invalid object', 'activitypub' ) );
}
/**
@ -85,7 +85,7 @@ class Factory {
! \is_object( $transformer ) ||
! $transformer instanceof Base
) {
return new \WP_Error( 'invalid_transformer', __( 'Invalid transformer', 'activitypub' ) );
return new \WP_Error( 'invalid_transformer', \__( 'Invalid transformer', 'activitypub' ) );
}
return $transformer;
@ -120,6 +120,6 @@ class Factory {
return new Activity_Object( $data );
}
return new \WP_Error( 'invalid_object', __( 'Invalid object', 'activitypub' ) );
return new \WP_Error( 'invalid_object', \__( 'Invalid object', 'activitypub' ) );
}
}

View File

@ -7,6 +7,10 @@
namespace Activitypub\Transformer;
use Activitypub\Activity\Activity;
use Activitypub\Activity\Actor;
use Activitypub\Activity\Base_Object;
use function Activitypub\is_activity;
use function Activitypub\is_actor;
@ -27,11 +31,11 @@ class Json extends Activity_Object {
// Check if the item is an Activity or an Object.
if ( is_activity( $item ) ) {
$class = '\Activitypub\Activity\Activity';
$class = Activity::class;
} elseif ( is_actor( $item ) ) {
$class = '\Activitypub\Activity\Actor';
$class = Actor::class;
} else {
$class = '\Activitypub\Activity\Base_Object';
$class = Base_Object::class;
}
$object = $class::init_from_array( $item );

View File

@ -8,7 +8,6 @@
namespace Activitypub\Transformer;
use Activitypub\Activity\Base_Object;
use Activitypub\Blocks;
use Activitypub\Collection\Actors;
use Activitypub\Collection\Interactions;
use Activitypub\Collection\Replies;
@ -21,6 +20,7 @@ use function Activitypub\get_content_visibility;
use function Activitypub\get_content_warning;
use function Activitypub\get_enclosures;
use function Activitypub\get_rest_url_by_path;
use function Activitypub\is_post_publicly_queryable;
use function Activitypub\is_single_user;
use function Activitypub\site_supports_blocks;
@ -90,6 +90,28 @@ class Post extends Base {
* @return \Activitypub\Activity\Base_Object The ActivityPub Object
*/
public function to_object() {
/*
* A redacted (password-protected or non-public) post is, from the
* Fediverse's perspective, gone — the soft-delete path that reaches here
* emits a Delete. Represent it as a Tombstone: content-free by type, so
* no body-derived field (content, summary, tags, @-mentions, location,
* attachments…) can ever leak, even one added to the transformer later.
*
* Address the teardown to the public collection. A post only reaches the
* soft-delete path after being federated, and only public / quiet-public
* posts federate (private and local ones never do), so the original
* audience was always public — broadcasting the Delete tears the copy
* down everywhere it may exist. Private/direct activities are deleted via
* their own outbox path and keep their original (non-public) audience, so
* they are not affected by this.
*/
if ( $this->is_redacted() ) {
$tombstone = $this->to_tombstone();
$tombstone->set_to( array( 'https://www.w3.org/ns/activitystreams#Public' ) );
return $tombstone;
}
$post = $this->item;
$object = parent::to_object();
@ -113,6 +135,9 @@ class Post extends Base {
$object = new Base_Object();
$object->set_type( 'Tombstone' );
$object->set_id( $this->get_id() );
// Preserve the permalink so the tombstone registry can resolve a request
// to it, even on sites whose ActivityPub ID is the post-ID URL (?p=123).
$object->set_url( $this->get_url() );
$object->set_former_type( $this->get_type() );
$object->set_published( $this->get_published() );
$object->set_updated( $this->get_updated() );
@ -175,7 +200,7 @@ class Post extends Base {
$user = Actors::get_by_id( $this->item->post_author );
if ( $user && ! is_wp_error( $user ) ) {
if ( $user && ! \is_wp_error( $user ) ) {
$this->actor_object = $user;
return $user;
}
@ -186,6 +211,20 @@ class Post extends Base {
/**
* Returns the ID of the Post.
*
* Posts past `activitypub_last_post_with_permalink_as_id` use the post-ID URL
* as their canonical ActivityPub ID — stable across slug changes. Posts at
* or below the threshold are *legacy* and use their permalink as the ID,
* which means a slug change effectively renames the federated object.
*
* Known limitation: a legacy post whose slug changes in the same save as
* a soft-delete transition (e.g. publish → draft + new post_name) will
* emit a Delete targeting the new permalink, while remote servers cached
* the original. The trash case mitigates this via the `wp_trash_post`
* hook caching the pre-transition URL in `_activitypub_canonical_url`,
* but draft / pending / private / password-applied transitions do not.
* If you maintain a site that pre-dates the ID migration, avoid editing
* the slug in the same save as the visibility change.
*
* @return string The Posts ID.
*/
public function get_id() {
@ -225,7 +264,7 @@ class Post extends Base {
break;
}
return \esc_url( $permalink );
return \esc_url_raw( $permalink );
}
/**
@ -265,7 +304,7 @@ class Post extends Base {
* @param int $id The attachment ID.
* @param string $image_size The image size to retrieve. Set to 'large' by default.
*/
$thumbnail = apply_filters(
$thumbnail = \apply_filters(
'activitypub_get_image',
$this->get_attachment_image_src( $id, $image_size ),
$id,
@ -280,7 +319,7 @@ class Post extends Base {
$image = array(
'type' => 'Image',
'url' => \esc_url( $thumbnail[0] ),
'url' => \esc_url_raw( $thumbnail[0] ),
'mediaType' => \esc_attr( $mime_type ),
);
@ -305,7 +344,7 @@ class Post extends Base {
$id = \get_post_thumbnail_id( $post_id );
} else {
// Try site_logo, falling back to site_icon, first.
$id = get_option( 'site_icon' );
$id = \get_option( 'site_icon' );
}
if ( ! $id ) {
@ -321,7 +360,7 @@ class Post extends Base {
* @param int $id The attachment ID.
* @param string $image_size The image size to retrieve. Set to 'large' by default.
*/
$thumbnail = apply_filters(
$thumbnail = \apply_filters(
'activitypub_get_image',
$this->get_attachment_image_src( $id, $image_size ),
$id,
@ -336,7 +375,7 @@ class Post extends Base {
$image = array(
'type' => 'Image',
'url' => \esc_url( $thumbnail[0] ),
'url' => \esc_url_raw( $thumbnail[0] ),
'mediaType' => \esc_attr( $mime_type ),
);
@ -358,19 +397,9 @@ class Post extends Base {
return $this->attachment;
}
/*
* Remove attachments from the Fediverse if a post was federated and then unpublished.
* Except in preview mode, where we want to show attachments.
*/
if ( ! $this->is_preview() && 'publish' !== \get_post_status( $this->item ) ) {
$this->attachment = array();
return $this->attachment;
}
$max_media = \get_post_meta( $this->item->ID, 'activitypub_max_image_attachments', true );
if ( ! is_numeric( $max_media ) ) {
if ( ! \is_numeric( $max_media ) ) {
$max_media = \get_option( 'activitypub_max_image_attachments', ACTIVITYPUB_MAX_IMAGE_ATTACHMENTS );
}
@ -523,7 +552,7 @@ class Post extends Base {
$tags[] = array(
'type' => 'Hashtag',
'href' => \esc_url( \get_tag_link( $post_tag->term_id ) ),
'href' => \esc_url_raw( \get_tag_link( $post_tag->term_id ) ),
'name' => esc_hashtag( $post_tag->name ),
);
}
@ -551,13 +580,6 @@ class Post extends Base {
return $this->summary;
}
// Remove Teaser from unpublished posts.
if ( ! $this->is_preview() && 'publish' !== \get_post_status( $this->item ) ) {
$this->summary = \__( '(This post is being modified)', 'activitypub' );
return $this->summary;
}
$this->summary = generate_post_summary( $this->item );
return $this->summary;
@ -601,13 +623,6 @@ class Post extends Base {
return $this->content;
}
// Remove Content from unpublished posts.
if ( ! $this->is_preview() && 'publish' !== \get_post_status( $this->item ) ) {
$this->content = \__( '(This post is being modified)', 'activitypub' );
return $this->content;
}
global $post;
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
@ -624,7 +639,7 @@ class Post extends Base {
\do_action( 'activitypub_before_get_content', $post );
// It seems that shortcodes are only applied to published posts.
if ( is_preview() ) {
if ( \is_preview() ) {
$post->post_status = 'publish';
}
@ -649,22 +664,6 @@ class Post extends Base {
return $this->content;
}
/**
* Generate HTML @ link for reply block.
*
* @deprecated 7.4.0 Use {@see Blocks::generate_reply_link()}.
*
* @param string $block_content The block content.
* @param array $block The block data.
*
* @return string The HTML @ link.
*/
public function generate_reply_link( $block_content, $block ) {
_deprecated_function( __METHOD__, '7.4.0', 'Activitypub\Blocks::generate_reply_link' );
return Blocks::generate_reply_link( $block_content, $block );
}
/**
* Returns the in-reply-to URL of the post.
*
@ -701,7 +700,7 @@ class Post extends Base {
return $this->in_reply_to;
}
if ( 1 === count( $reply_urls ) ) {
if ( 1 === \count( $reply_urls ) ) {
$this->in_reply_to = \current( $reply_urls );
return $this->in_reply_to;
@ -760,8 +759,8 @@ class Post extends Base {
// Both latitude and longitude are required for a valid location.
// Use is_numeric() instead of empty() since 0 is a valid coordinate (Equator/Prime Meridian).
$has_latitude = isset( $meta['geo_latitude'][0] ) && is_numeric( $meta['geo_latitude'][0] );
$has_longitude = isset( $meta['geo_longitude'][0] ) && is_numeric( $meta['geo_longitude'][0] );
$has_latitude = isset( $meta['geo_latitude'][0] ) && \is_numeric( $meta['geo_latitude'][0] );
$has_longitude = isset( $meta['geo_longitude'][0] ) && \is_numeric( $meta['geo_longitude'][0] );
if ( ! $has_latitude || ! $has_longitude ) {
return null;
@ -809,7 +808,7 @@ class Post extends Base {
*
* @return array The filtered mentions.
*/
$this->mentions = apply_filters(
$this->mentions = \apply_filters(
'activitypub_extract_mentions',
array(),
$this->item->post_content . ' ' . $this->item->post_excerpt,
@ -820,33 +819,34 @@ class Post extends Base {
}
/**
* Transform Embed blocks to block level link.
* Whether the post should be redacted from ActivityPub representations.
*
* Remote servers will simply drop iframe elements, rendering incomplete content.
* Redaction is fail-closed at a single boundary: `to_object()` returns a
* Tombstone instead of transforming the post, so no body-derived field
* (content, summary, name, preview, attachments, image/icon, tags, mentions,
* in-reply-to, location) is ever read — not even one added to the transformer
* later. This is the only caller of this gate.
*
* @deprecated 7.4.0 Use {@see Blocks::revert_embed_links()}.
* A post is redacted exactly when it is not publicly queryable — the same
* predicate the scheduler uses to decide a federated post should emit a
* Delete (`is_post_publicly_queryable()`), so the two never disagree. That
* covers non-public status, password protection, the `local`/`private`
* content-visibility meta, and a post type that no longer supports
* ActivityPub. The Fediverse Preview keeps working because
* `is_post_publicly_queryable()` itself treats a draft/pending/scheduled
* post as queryable during a `?preview=true` request from a user who can
* edit it.
*
* @see https://www.w3.org/TR/activitypub/#security-sanitizing-content
* @see https://www.w3.org/wiki/ActivityPub/Primer/HTML
* Note: we deliberately rely on `is_post_publicly_queryable()` rather than
* `post_password_required()`. Federation output is per-instance, never
* per-request, and `post_password_required()` returns false when a valid
* `wp-postpass` cookie is on the current request (e.g. an editor who unlocked
* the post), which would leak the protected body into an outbox snapshot.
*
* @param string $block_content The block content (html).
* @param object $block The block object.
*
* @return string A block level link
* @return boolean True if the post must be redacted, false otherwise.
*/
public function revert_embed_links( $block_content, $block ) {
_deprecated_function( __METHOD__, '7.4.0', 'Activitypub\Blocks::revert_embed_links' );
return Blocks::revert_embed_links( $block_content, $block );
}
/**
* Check if the post is a preview.
*
* @return boolean True if the post is a preview, false otherwise.
*/
private function is_preview() {
return defined( 'ACTIVITYPUB_PREVIEW' ) && ACTIVITYPUB_PREVIEW;
protected function is_redacted() {
return ! is_post_publicly_queryable( $this->item );
}
/**
@ -954,6 +954,51 @@ class Post extends Base {
}
}
break;
case 'core/media-text':
if ( ! empty( $block['attrs']['mediaId'] ) ) {
$media_id = $block['attrs']['mediaId'];
// Media & Text holds either an image or a video; the default is image.
if ( 'video' === ( $block['attrs']['mediaType'] ?? 'image' ) ) {
$video = array( 'id' => $media_id );
// The poster is stored as an HTML attribute on the <video> tag, not in block attrs.
$processor = new \WP_HTML_Tag_Processor( $block['innerHTML'] );
if ( $processor->next_tag( array( 'tag_name' => 'video' ) ) ) {
$poster = $processor->get_attribute( 'poster' );
if ( ! empty( $poster ) ) {
$video['icon'] = \esc_url_raw( $poster );
}
}
$media['video'][] = $video;
} else {
$alt = '';
$processor = new \WP_HTML_Tag_Processor( $block['innerHTML'] );
if ( $processor->next_tag( array( 'tag_name' => 'img' ) ) ) {
$alt = $processor->get_attribute( 'alt' ) ?? '';
}
// Update alt in place if the image was already collected, so a
// duplicate ID does not get dropped (and its alt lost) later.
$found = false;
foreach ( $media['image'] as $i => $image ) {
if ( isset( $image['id'] ) && $image['id'] === $media_id ) {
$media['image'][ $i ]['alt'] = $alt;
$found = true;
break;
}
}
if ( ! $found ) {
$media['image'][] = array(
'id' => $media_id,
'alt' => $alt,
);
}
}
}
break;
case 'core/audio':
if ( ! empty( $block['attrs']['id'] ) ) {
$media['audio'][] = array( 'id' => $block['attrs']['id'] );
@ -979,9 +1024,9 @@ class Post extends Base {
case 'jetpack/slideshow':
case 'jetpack/tiled-gallery':
if ( ! empty( $block['attrs']['ids'] ) ) {
$media['image'] = array_merge(
$media['image'] = \array_merge(
$media['image'],
array_map(
\array_map(
static function ( $id ) {
return array( 'id' => $id );
},
@ -1028,22 +1073,7 @@ class Post extends Base {
return $media[ $type ];
}
return array_filter( array_merge( ...array_values( $media ) ) );
}
/**
* Converts a WordPress Attachment to an ActivityPub Attachment.
*
* @deprecated 7.2.0 Use {@see Base::transform_attachment()} instead.
*
* @param array $media The Attachment array.
*
* @return array The ActivityPub Attachment.
*/
public function wp_attachment_to_activity_attachment( $media ) {
_deprecated_function( __METHOD__, '7.2.0', '\Activitypub\Transformer\Base::transform_attachment()' );
return parent::transform_attachment( $media );
return \array_filter( \array_merge( ...\array_values( $media ) ) );
}
/**
@ -1054,7 +1084,7 @@ class Post extends Base {
* @return string The context of the post.
*/
protected function get_context() {
return get_rest_url_by_path( sprintf( 'posts/%d/context', $this->item->ID ) );
return get_rest_url_by_path( \sprintf( 'posts/%d/context', $this->item->ID ) );
}
/**
@ -1101,7 +1131,7 @@ class Post extends Base {
* @param \WP_Post $item The WordPress post object being transformed.
* @param string $type ActivityStreams 2.0 Object-Type for the post.
*/
return apply_filters( 'activitypub_object_content_template', $template, $this->item, $type );
return \apply_filters( 'activitypub_object_content_template', $template, $this->item, $type );
}
/**
@ -1120,7 +1150,7 @@ class Post extends Base {
*/
public function get_likes() {
return array(
'id' => get_rest_url_by_path( sprintf( 'posts/%d/likes', $this->item->ID ) ),
'id' => get_rest_url_by_path( \sprintf( 'posts/%d/likes', $this->item->ID ) ),
'type' => 'Collection',
'totalItems' => Interactions::count_by_type( $this->item->ID, 'like' ),
);
@ -1133,7 +1163,7 @@ class Post extends Base {
*/
public function get_shares() {
return array(
'id' => get_rest_url_by_path( sprintf( 'posts/%d/shares', $this->item->ID ) ),
'id' => get_rest_url_by_path( \sprintf( 'posts/%d/shares', $this->item->ID ) ),
'type' => 'Collection',
'totalItems' => Interactions::count_by_type( $this->item->ID, 'repost' ) + Interactions::count_by_type( $this->item->ID, 'quote' ),
);
@ -1170,7 +1200,7 @@ class Post extends Base {
switch ( $policy ) {
case ACTIVITYPUB_INTERACTION_POLICY_FOLLOWERS:
return array( 'automaticApproval' => get_rest_url_by_path( sprintf( 'actors/%d/followers', $this->item->post_author ) ) );
return array( 'automaticApproval' => get_rest_url_by_path( \sprintf( 'actors/%d/followers', $this->item->post_author ) ) );
case ACTIVITYPUB_INTERACTION_POLICY_ME:
return array( 'automaticApproval' => $this->get_self_interaction_policy() );

View File

@ -7,6 +7,8 @@
namespace Activitypub\Transformer;
use Activitypub\Activity\Base_Object;
/**
* Term Transformer Class.
*/
@ -19,7 +21,7 @@ class Term extends Base {
* @return \Activitypub\Activity\Base_Object|\WP_Error The OrderedCollection or WP_Error on failure.
*/
public function to_object() {
$base_object = new \Activitypub\Activity\Base_Object();
$base_object = new Base_Object();
$base_object->{'@context'} = 'https://www.w3.org/ns/activitystreams';
$base_object->set_type( 'OrderedCollection' );
$base_object->set_id( $this->get_id() );
@ -61,6 +63,6 @@ class Term extends Base {
return '';
}
return \esc_url( $term_link );
return \esc_url_raw( $term_link );
}
}