updated plugin ActivityPub version 8.3.0

This commit is contained in:
2026-06-03 21:28:46 +00:00
committed by Gitium
parent a4b78ec277
commit 6fe182458a
340 changed files with 43232 additions and 7568 deletions

View File

@ -18,10 +18,29 @@ use Activitypub\Activity\Extended_Object\Place;
*
* @see https://www.w3.org/TR/activitystreams-core/#activities
* @see https://www.w3.org/TR/activitystreams-core/#intransitiveactivities
*
* @method string|array get_actor() Gets one or more entities that performed or are expected to perform the activity.
* @method string|array|null get_instrument() Gets one or more objects used in the completion of an Activity.
* @method Base_Object|string|array|null get_object() Gets the direct object of the activity.
* @method string|string[]|null get_origin() Gets the origin property of the activity.
* @method array|null get_replies() Gets the collection of responses to this activity.
* @method string|null get_result() Gets the result property of the activity.
* @method string|string[]|null get_target() Gets the target property of the activity.
*
* @method Activity set_actor( string|array $actor ) Sets one or more entities that performed the activity.
* @method Activity set_instrument( string|array $instrument ) Sets one or more objects used in the completion of an Activity.
* @method Activity set_origin( string|array|null $origin ) Sets the origin property of the activity.
* @method Activity set_replies( array $replies ) Sets the collection of responses to this activity.
* @method Activity set_result( string|null $result ) Sets the result property of the activity.
* @method Activity set_target( string|array|null $target ) Sets the target property of the activity.
*/
class Activity extends Base_Object {
const JSON_LD_CONTEXT = array(
'https://www.w3.org/ns/activitystreams',
array(
'toot' => 'http://joinmastodon.org/ns#',
'QuoteRequest' => 'toot:QuoteRequest',
),
);
/**
@ -50,6 +69,7 @@ class Activity extends Base_Object {
'Listen',
'Move',
'Offer',
'QuoteRequest', // @see https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md
'Read',
'Reject',
'Remove',
@ -75,7 +95,7 @@ class Activity extends Base_Object {
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object-term
*
* @var string|Base_Object|null
* @var string|Base_Object|array|null
*/
protected $object;
@ -102,7 +122,7 @@ class Activity extends Base_Object {
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-target
*
* @var string|array
* @var string|array|null
*/
protected $target;
@ -114,7 +134,7 @@ class Activity extends Base_Object {
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-result
*
* @var string|Base_Object
* @var string|Base_Object|null
*/
protected $result;
@ -126,7 +146,7 @@ class Activity extends Base_Object {
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies
*
* @var array
* @var array|null
*/
protected $replies;
@ -140,7 +160,7 @@ class Activity extends Base_Object {
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-origin
*
* @var string|array
* @var string|array|null
*/
protected $origin;
@ -150,7 +170,7 @@ class Activity extends Base_Object {
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument
*
* @var string|array
* @var string|array|null
*/
protected $instrument;
@ -162,33 +182,17 @@ class Activity extends Base_Object {
*
* @see https://www.w3.org/TR/activitypub/#object-without-create
*
* @param array|string|Base_Object|Activity|Actor|null $data Activity object.
* @param array|string|Base_Object|Activity|Actor|null $data Activity object.
*/
public function set_object( $data ) {
$object = $data;
// Convert array to appropriate object type.
if ( is_array( $data ) ) {
$type = $data['type'] ?? null;
if ( in_array( $type, self::TYPES, true ) ) {
$object = self::init_from_array( $data );
} elseif ( in_array( $type, Actor::TYPES, true ) ) {
$object = Actor::init_from_array( $data );
} elseif ( in_array( $type, Base_Object::TYPES, true ) ) {
switch ( $type ) {
case 'Event':
$object = Event::init_from_array( $data );
break;
case 'Place':
$object = Place::init_from_array( $data );
break;
default:
$object = Base_Object::init_from_array( $data );
break;
}
if ( array_is_list( $data ) ) {
$object = array_map( array( $this, 'maybe_convert_to_object' ), $data );
} else {
$object = Generic_Object::init_from_array( $data );
$object = $this->maybe_convert_to_object( $data );
}
}
@ -202,14 +206,14 @@ class Activity extends Base_Object {
public function pre_fill_activity_from_object() {
$object = $this->get_object();
// Check if `$data` is a URL and use it to generate an ID then.
// Check if `$object` is a URL and use it to generate an ID then.
if ( is_string( $object ) && filter_var( $object, FILTER_VALIDATE_URL ) && ! $this->get_id() ) {
$this->set( 'id', $object . '#activity-' . strtolower( $this->get_type() ) . '-' . time() );
return;
}
// Check if `$data` is an object and copy some properties otherwise do nothing.
// Check if `$object` is an object and copy some properties otherwise do nothing.
if ( ! is_object( $object ) ) {
return;
}
@ -237,6 +241,10 @@ class Activity extends Base_Object {
$this->set( 'in_reply_to', $object->get_in_reply_to() );
}
if ( $object->get_interaction_policy() && ! $this->get_interaction_policy() ) {
$this->set( 'interaction_policy', $object->get_interaction_policy() );
}
if ( $object->get_id() && ! $this->get_id() ) {
$id = strtok( $object->get_id(), '#' );
if ( $object->get_updated() ) {
@ -256,7 +264,7 @@ class Activity extends Base_Object {
* @return array $context A compacted JSON-LD context.
*/
public function get_json_ld_context() {
if ( $this->object instanceof Base_Object ) {
if ( \is_object( $this->object ) ) {
$class = get_class( $this->object );
if ( $class && $class::JSON_LD_CONTEXT ) {
// Without php 5.6 support this could be just: 'return $this->object::JSON_LD_CONTEXT;'.
@ -266,4 +274,41 @@ class Activity extends Base_Object {
return static::JSON_LD_CONTEXT;
}
/**
* Convert data to the appropriate object type if it has an ActivityPub type.
*
* @param array|string|Base_Object|Activity|Actor|null $data The data to convert.
*
* @return Activity|Actor|Base_Object|Generic_Object|string|\WP_Error|null The converted object or original data.
*/
private function maybe_convert_to_object( $data ) {
if ( ! is_array( $data ) ) {
return $data;
}
$type = $data['type'] ?? null;
if ( in_array( $type, self::TYPES, true ) ) {
$object = self::init_from_array( $data );
} elseif ( in_array( $type, Actor::TYPES, true ) ) {
$object = Actor::init_from_array( $data );
} elseif ( in_array( $type, Base_Object::TYPES, true ) ) {
switch ( $type ) {
case 'Event':
$object = Event::init_from_array( $data );
break;
case 'Place':
$object = Place::init_from_array( $data );
break;
default:
$object = Base_Object::init_from_array( $data );
break;
}
} else {
$object = Generic_Object::init_from_array( $data );
}
return $object;
}
}

View File

@ -16,6 +16,52 @@ namespace Activitypub\Activity;
* Represents an individual actor.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types
*
* @method string[]|null get_also_known_as() Gets the also known as property of the actor.
* @method array|null get_attribution_domains() Gets domains allowed to use fediverse:creator for this actor.
* @method bool|null get_discoverable() Gets whether the actor is discoverable.
* @method string[]|null get_endpoints() Gets the endpoint property of the actor.
* @method string|null get_featured() Gets the featured posts collection of the actor.
* @method string|null get_featured_tags() Gets the featured tags collection of the actor.
* @method string|null get_followers() Gets the followers collection of the actor.
* @method string|null get_following() Gets the following collection of the actor.
* @method array|null get_implements() Gets the list of implemented specifications.
* @method string|null get_inbox() Gets the inbox property of the actor.
* @method bool|null get_indexable() Gets whether the actor is indexable.
* @method bool|null get_invisible() Gets whether the actor is invisible.
* @method string|null get_liked() Gets the liked collection of the actor.
* @method bool|null get_manually_approves_followers() Gets whether the actor manually approves followers.
* @method string|null get_moderators() Gets the moderators endpoint URL.
* @method string|null get_moved_to() Gets the target of the actor move.
* @method string|null get_outbox() Gets the outbox property of the actor.
* @method bool|null get_posting_restricted_to_mods() Gets whether posting is restricted to moderators.
* @method string|null get_preferred_username() Gets the preferred username of the actor.
* @method string|array|null get_public_key() Gets the public key of the actor.
* @method array get_streams() Gets the list of supplementary collections.
* @method string|null get_webfinger() Gets the WebFinger resource.
*
* @method Actor set_also_known_as( array $also_known_as ) Sets the also known as property of the actor.
* @method Actor set_attribution_domains( array $attribution_domains ) Sets domains allowed to use fediverse:creator for this actor.
* @method Actor set_discoverable( bool $discoverable ) Sets whether the actor is discoverable.
* @method Actor set_endpoints( string|array $endpoints ) Sets the endpoint property of the actor.
* @method Actor set_featured( string $featured ) Sets the featured posts collection of the actor.
* @method Actor set_featured_tags( string $featured_tags ) Sets the featured tags collection of the actor.
* @method Actor set_followers( string $followers ) Sets the followers collection of the actor.
* @method Actor set_following( string $following ) Sets the following collection of the actor.
* @method Actor set_implements( array $implements ) Sets the list of implemented specifications.
* @method Actor set_inbox( string $inbox ) Sets the inbox property of the actor.
* @method Actor set_indexable( bool $indexable ) Sets whether the actor is indexable.
* @method Actor set_invisible( bool $invisible ) Sets whether the actor is invisible.
* @method Actor set_liked( string $liked ) Sets the liked collection of the actor.
* @method Actor set_manually_approves_followers( bool $manually_approves_followers ) Sets whether the actor manually approves followers.
* @method Actor set_moderators( string $moderators ) Sets the moderators endpoint URL.
* @method Actor set_moved_to( string $moved_to ) Sets the target of the actor move.
* @method Actor set_outbox( string $outbox ) Sets the outbox property of the actor.
* @method Actor set_posting_restricted_to_mods( bool $posting_restricted_to_mods ) Sets whether posting is restricted to moderators.
* @method Actor set_preferred_username( string $preferred_username ) Sets the preferred username of the actor.
* @method Actor set_public_key( string|array $public_key ) Sets the public key of the actor.
* @method Actor set_streams( array $streams ) Sets the list of supplementary collections.
* @method Actor set_webfinger( string $webfinger ) Sets the WebFinger resource.
*/
class Actor extends Base_Object {
// Reduced context for actors. TODO: still unused.
@ -27,6 +73,7 @@ class Actor extends Base_Object {
'schema' => 'http://schema.org#',
'toot' => 'http://joinmastodon.org/ns#',
'lemmy' => 'https://join-lemmy.org/ns#',
'litepub' => 'http://litepub.social/ns#',
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
'PropertyValue' => 'schema:PropertyValue',
'value' => 'schema:value',
@ -55,9 +102,15 @@ class Actor extends Base_Object {
'@id' => 'toot:attributionDomains',
'@type' => '@id',
),
'implements' => array(
'@id' => 'https://w3id.org/fep/844e/implements',
'@type' => '@id',
'@container' => '@list',
),
'postingRestrictedToMods' => 'lemmy:postingRestrictedToMods',
'discoverable' => 'toot:discoverable',
'indexable' => 'toot:indexable',
'invisible' => 'litepub:invisible',
),
);
@ -166,14 +219,13 @@ class Actor extends Base_Object {
protected $endpoints;
/**
* It's not part of the ActivityPub protocol but it's a quite common
* It's not part of the ActivityPub protocol, but it's a quite common
* practice to handle an actor public key with a publicKey array:
* [
* 'id' => 'https://my-example.com/actor#main-key'
* 'owner' => 'https://my-example.com/actor',
* 'id' => 'https://my-example.com/actor#main-key'
* 'owner' => 'https://my-example.com/actor',
* 'publicKeyPem' => '-----BEGIN PUBLIC KEY-----
* MIIBI [...]
* DQIDAQAB
* [...]
* -----END PUBLIC KEY-----'
* ]
*
@ -184,8 +236,8 @@ class Actor extends Base_Object {
protected $public_key;
/**
* It's not part of the ActivityPub protocol but it's a quite common
* practice to lock an account. If anabled, new followers will not be
* It's not part of the ActivityPub protocol, but it's a quite common
* practice to lock an account. If enabled, new followers will not be
* automatically accepted, but will instead require you to manually
* approve them.
*
@ -195,7 +247,7 @@ class Actor extends Base_Object {
*
* @context as:manuallyApprovesFollowers
*
* @var boolean
* @var boolean|null
*/
protected $manually_approves_followers = false;
@ -205,7 +257,7 @@ class Actor extends Base_Object {
*
* @see https://blog.joinmastodon.org/2024/07/highlighting-journalism-on-mastodon/
*
* @var array
* @var array|null
*/
protected $attribution_domains = null;
@ -219,7 +271,102 @@ class Actor extends Base_Object {
/**
* The alsoKnownAs of the actor.
*
* @var array
* @var array|null
*/
protected $also_known_as;
/**
* The Featured-Posts.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#featured
*
* @context {
* "@id": "http://joinmastodon.org/ns#featured",
* "@type": "@id"
* }
*
* @var string|null
*/
protected $featured;
/**
* The Featured-Tags.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#featuredTags
*
* @context {
* "@id": "http://joinmastodon.org/ns#featuredTags",
* "@type": "@id"
* }
*
* @var string|null
*/
protected $featured_tags;
/**
* Whether the User is discoverable.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#discoverable
*
* @context http://joinmastodon.org/ns#discoverable
*
* @var boolean|null
*/
protected $discoverable;
/**
* Whether the User is indexable.
*
* @see https://docs.joinmastodon.org/spec/activitypub/#indexable
*
* @context http://joinmastodon.org/ns#indexable
*
* @var boolean|null
*/
protected $indexable;
/**
* The WebFinger Resource.
*
* @see https://codeberg.org/fediverse/fep/src/branch/main/fep/2c59/fep-2c59.md
*
* @var string|null
*/
protected $webfinger;
/**
* URL to the Moderators endpoint.
*
* @see https://join-lemmy.org/docs/contributors/05-federation.html
*
* @var string|null
*/
protected $moderators;
/**
* Restrict posting to mods.
*
* @see https://join-lemmy.org/docs/contributors/05-federation.html
*
* @var boolean|null
*/
protected $posting_restricted_to_mods;
/**
* Listing Implemented Specifications on the Application Actor
*
* @see https://codeberg.org/fediverse/fep/src/branch/main/fep/844e/fep-844e.md
*
* @var array|null
*/
protected $implements;
/**
* Whether the User is invisible.
*
* @see https://litepub.social/
*
* @var boolean|null
*/
protected $invisible = null;
}

View File

@ -9,6 +9,8 @@
namespace Activitypub\Activity;
use Activitypub\Activity\Extended_Object\Place;
/**
* Base_Object is an implementation of one of the
* Activity Streams Core Types.
@ -21,48 +23,96 @@ namespace Activitypub\Activity;
*
* @see https://www.w3.org/TR/activitystreams-core/#object
*
* @method string|null get_actor() Gets one or more entities that performed or are expected to perform the activity.
* @method string|null get_attributed_to() Gets the entity attributed as the original author.
* @method array|null get_attachment() Gets the attachment property of the object.
* @method array|null get_cc() Gets the secondary recipients of the object.
* @method string|null get_content() Gets the content property of the object.
* @method array|null get_icon() Gets the icon property of the object.
* @method string|null get_id() Gets the object's unique global identifier.
* @method array|null get_image() Gets the image property of the object.
* @method array|string|null get_in_reply_to() Gets the objects this object is in reply to.
* @method string|null get_name() Gets the natural language name of the object.
* @method Base_Object|string|null get_object() Gets the direct object of the activity.
* @method string|null get_published() Gets the date and time the object was published in ISO 8601 format.
* @method string|null get_summary() Gets the natural language summary of the object.
* @method array|null get_tag() Gets the tag property of the object.
* @method array|string|null get_to() Gets the primary recipients of the object.
* @method string get_type() Gets the type of the object.
* @method string|null get_updated() Gets the date and time the object was updated in ISO 8601 format.
* @method string|null get_url() Gets the URL of the object.
* @method array|string|null get_attachment() Gets the attachment property of the object.
* @method array|string|null get_attributed_to() Gets the entity attributed as the original author.
* @method string|null get_audience() Gets the total population of entities for which the object can be considered relevant.
* @method string[]|string|null get_bcc() Gets the private secondary audience of the object.
* @method string[]|string|null get_bto() Gets the private primary audience of the object.
* @method string[]|string|null get_cc() Gets the secondary recipients of the object.
* @method string|null get_content() Gets the content property of the object.
* @method string[]|null get_content_map() Gets the content map property of the object.
* @method string|null get_context() Gets the context within which the object exists.
* @method array|null get_dcterms() Gets the Dublin Core terms property of the object.
* @method string|null get_duration() Gets the duration property of time-bound resources.
* @method string|null get_end_time() Gets the date and time describing the ending time of the object.
* @method string|null get_generator() Gets the entity that generated the object.
* @method string[]|null get_icon() Gets the icon property of the object.
* @method string|null get_id() Gets the object's unique global identifier.
* @method string[]|null get_image() Gets the image property of the object.
* @method string[]|string|null get_in_reply_to() Gets the objects this object is in reply to.
* @method array|null get_interaction_policy() Gets the interaction policy property of the object.
* @method array|null get_likes() Gets the collection of likes for this object.
* @method array|string|null|Place get_location() Gets the physical or logical locations associated with the object.
* @method string|null get_media_type() Gets the MIME media type of the content property.
* @method string|null get_name() Gets the natural language name of the object.
* @method string[]|null get_name_map() Gets the name map property of the object.
* @method string|null get_preview() Gets the entity that provides a preview of this object.
* @method string|null get_published() Gets the date and time the object was published in ISO 8601 format.
* @method string|null get_quote() Gets the quote property of the object (FEP-044f).
* @method string|null get_quote_url() Gets the quoteUrl property of the object.
* @method string|null get_quote_uri() Gets the quoteUri property of the object.
* @method string|null get__misskey_quote() Gets the _misskey_quote property of the object.
* @method string|array|null get_replies() Gets the collection of responses to this object.
* @method bool|null get_sensitive() Gets the sensitive property of the object.
* @method array|null get_shares() Gets the collection of shares for this object.
* @method array|null get_source() Gets the source property indicating content markup derivation.
* @method string|null get_start_time() Gets the date and time describing the starting time of the object.
* @method string|null get_summary() Gets the natural language summary of the object.
* @method string[]|null get_summary_map() Gets the summary map property of the object.
* @method array[]|null get_tag() Gets the tag property of the object.
* @method string[]|string|null get_to() Gets the primary recipients of the object.
* @method string get_type() Gets the type of the object.
* @method string|null get_updated() Gets the date and time the object was updated in ISO 8601 format.
* @method string|null get_url() Gets the URL of the object.
* @method string|null get_former_type() Gets the former type of a Tombstone object.
* @method string|null get_deleted() Gets the date and time the object was deleted in ISO 8601 format.
*
* @method string|array add_cc( string|array $cc ) Adds one or more entities to the secondary audience of the object.
* @method string|array add_to( string|array $to ) Adds one or more entities to the primary audience of the object.
* @method string|string[] add_cc( string|array $cc ) Adds one or more entities to the secondary audience of the object.
* @method string|string[] add_to( string|array $to ) Adds one or more entities to the primary audience of the object.
*
* @method Base_Object set_actor( string|array $actor ) Sets one or more entities that performed the activity.
* @method Base_Object set_attachment( array $attachment ) Sets the attachment property of the object.
* @method Base_Object set_attributed_to( string $attributed_to ) Sets the entity attributed as the original author.
* @method Base_Object set_cc( array|string $cc ) Sets the secondary recipients of the object.
* @method Base_Object set_content( string $content ) Sets the content property of the object.
* @method Base_Object set_content_map( array $content_map ) Sets the content property of the object.
* @method Base_Object set_icon( array $icon ) Sets the icon property of the object.
* @method Base_Object set_id( string $id ) Sets the object's unique global identifier.
* @method Base_Object set_image( array $image ) Sets the image property of the object.
* @method Base_Object set_name( string $name ) Sets the natural language name of the object.
* @method Base_Object set_origin( string $origin ) Sets the origin property of the object.
* @method Base_Object set_published( string $published ) Sets the date and time the object was published in ISO 8601 format.
* @method Base_Object set_sensitive( bool $sensitive ) Sets the sensitive property of the object.
* @method Base_Object set_summary( string $summary ) Sets the natural language summary of the object.
* @method Base_Object set_summary_map( array|null $summary_map ) Sets the summary property of the object.
* @method Base_Object set_target( string $target ) Sets the target property of the object.
* @method Base_Object set_to( array|string $to ) Sets the primary recipients of the object.
* @method Base_Object set_type( string $type ) Sets the type of the object.
* @method Base_Object set_updated( string $updated ) Sets the date and time the object was updated in ISO 8601 format.
* @method Base_Object set_url( string $url ) Sets the URL of the object.
* @method Base_Object set_attachment( array $attachment ) Sets the attachment property of the object.
* @method Base_Object set_attributed_to( string $attributed_to ) Sets the entity attributed as the original author.
* @method Base_Object set_audience( string $audience ) Sets the total population of entities for which the object can be considered relevant.
* @method Base_Object set_bcc( array|string $bcc ) Sets the private secondary audience of the object.
* @method Base_Object set_bto( array|string $bto ) Sets the private primary audience of the object.
* @method Base_Object set_cc( array|string $cc ) Sets the secondary recipients of the object.
* @method Base_Object set_content( string $content ) Sets the content property of the object.
* @method Base_Object set_content_map( array $content_map ) Sets the content property of the object.
* @method Base_Object set_context( string $context ) Sets the context within which the object exists.
* @method Base_Object set_dcterms( array $dcterms ) Sets the Dublin Core terms property of the object.
* @method Base_Object set_duration( string $duration ) Sets the duration property of time-bound resources.
* @method Base_Object set_end_time( string $end_time ) Sets the date and time describing the ending time of the object.
* @method Base_Object set_generator( string $generator ) Sets the entity that generated the object.
* @method Base_Object set_icon( array $icon ) Sets the icon property of the object.
* @method Base_Object set_id( string $id ) Sets the object's unique global identifier.
* @method Base_Object set_image( array $image ) Sets the image property of the object.
* @method Base_Object set_in_reply_to( string|string[] $in_reply_to ) Sets the is in reply to property of the object.
* @method Base_Object set_interaction_policy( array|null $policy ) Sets the interaction policy property of the object.
* @method Base_Object set_likes( array $likes ) Sets the collection of likes for this object.
* @method Base_Object set_location( array|string|Place $location ) Sets the physical or logical locations associated with the object.
* @method Base_Object set_media_type( string $media_type ) Sets the MIME media type of the content property.
* @method Base_Object set_name( string $name ) Sets the natural language name of the object.
* @method Base_Object set_name_map( array|null $name_map ) Sets the name map property of the object.
* @method Base_Object set_preview( string $preview ) Sets the entity that provides a preview of this object.
* @method Base_Object set_published( string|null $published ) Sets the date and time the object was published in ISO 8601 format.
* @method Base_Object set_quote( string $quote ) Sets the quote property of the object (FEP-044f).
* @method Base_Object set_quote_url( string $quote_url ) Sets the quoteUrl property of the object.
* @method Base_Object set_quote_uri( string $quote_uri ) Sets the quoteUri property of the object.
* @method Base_Object set__misskey_quote( mixed $misskey_quote ) Sets the _misskey_quote property of the object.
* @method Base_Object set_replies( string|array $replies ) Sets the collection of responses to this object.
* @method Base_Object set_sensitive( bool|null $sensitive ) Sets the sensitive property of the object.
* @method Base_Object set_shares( array $shares ) Sets the collection of shares for this object.
* @method Base_Object set_source( array $source ) Sets the source property indicating content markup derivation.
* @method Base_Object set_start_time( string $start_time ) Sets the date and time describing the starting time of the object.
* @method Base_Object set_summary( string $summary ) Sets the natural language summary of the object.
* @method Base_Object set_summary_map( array|null $summary_map ) Sets the summary property of the object.
* @method Base_Object set_tag( array|null $tag ) Sets the tag property of the object.
* @method Base_Object set_to( string|string[] $to ) Sets the primary recipients of the object.
* @method Base_Object set_type( string $type ) Sets the type of the object.
* @method Base_Object set_updated( string $updated ) Sets the date and time the object was updated in ISO 8601 format.
* @method Base_Object set_url( string $url ) Sets the URL of the object.
* @method Base_Object set_former_type( string $former_type ) Sets the former type of a Tombstone object.
* @method Base_Object set_deleted( string $deleted ) Sets the date and time the object was deleted in ISO 8601 format.
*/
class Base_Object extends Generic_Object {
/**
@ -73,8 +123,45 @@ class Base_Object extends Generic_Object {
const JSON_LD_CONTEXT = array(
'https://www.w3.org/ns/activitystreams',
array(
'Hashtag' => 'as:Hashtag',
'sensitive' => 'as:sensitive',
'Hashtag' => 'as:Hashtag',
'sensitive' => 'as:sensitive',
'dcterms' => 'http://purl.org/dc/terms/',
'gts' => 'https://gotosocial.org/ns#',
'schema' => 'http://schema.org/',
'exifData' => 'schema:exifData',
'PropertyValue' => 'schema:PropertyValue',
'interactionPolicy' => array(
'@id' => 'gts:interactionPolicy',
'@type' => '@id',
),
'canQuote' => array(
'@id' => 'gts:canQuote',
'@type' => '@id',
),
'canReply' => array(
'@id' => 'gts:canReply',
'@type' => '@id',
),
'canLike' => array(
'@id' => 'gts:canLike',
'@type' => '@id',
),
'canAnnounce' => array(
'@id' => 'gts:canAnnounce',
'@type' => '@id',
),
'automaticApproval' => array(
'@id' => 'gts:automaticApproval',
'@type' => '@id',
),
'manualApproval' => array(
'@id' => 'gts:manualApproval',
'@type' => '@id',
),
'always' => array(
'@id' => 'gts:always',
'@type' => '@id',
),
),
);
@ -132,7 +219,7 @@ class Base_Object extends Generic_Object {
/**
* One or more entities that represent the total population of
* entities for which the object can considered to be relevant.
* entities for which the object can be considered to be relevant.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audience
*
@ -180,6 +267,25 @@ class Base_Object extends Generic_Object {
*/
protected $content_map;
/**
* The date and time at which the object was deleted.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-deleted
*
* @var string|null
*/
protected $deleted;
/**
* The former type of the object. Used in Tombstone objects to
* indicate the type of the object prior to deletion.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-formertype
*
* @var string|null
*/
protected $former_type;
/**
* A simple, human-readable, plain-text name for the object.
* HTML markup MUST NOT be included.
@ -258,7 +364,7 @@ class Base_Object extends Generic_Object {
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-location
*
* @var string|null
* @var string|null|Place
*/
protected $location;
@ -395,9 +501,9 @@ class Base_Object extends Generic_Object {
/**
* When the object describes a time-bound resource, such as an audio
* or video, a meeting, etc, the duration property indicates the
* or video, a meeting, etc., the duration property indicates the
* object's approximate duration.
* The value MUST be expressed as an xsd:duration as defined by
* The value MUST be expressed as a xsd:duration as defined by
* xmlschema11-2, section 3.3.6 (e.g. a period of 5 seconds is
* represented as "PT5S").
*
@ -414,7 +520,7 @@ class Base_Object extends Generic_Object {
*
* @see https://www.w3.org/TR/activitypub/#source-property
*
* @var array
* @var array|null
*/
protected $source;
@ -434,7 +540,7 @@ class Base_Object extends Generic_Object {
*
* @see https://www.w3.org/TR/activitypub/#likes
*
* @var array
* @var array|null
*/
protected $likes;
@ -444,7 +550,7 @@ class Base_Object extends Generic_Object {
*
* @see https://www.w3.org/TR/activitypub/#shares
*
* @var array
* @var array|null
*/
protected $shares;
@ -455,10 +561,70 @@ class Base_Object extends Generic_Object {
*
* @see https://docs.joinmastodon.org/spec/activitypub/#sensitive
*
* @var boolean
* @var boolean|null
*/
protected $sensitive;
/**
* The dcterms namespace.
*
* @see https://codeberg.org/fediverse/fep/src/branch/main/fep/b2b8/fep-b2b8.md#sensitive
* @see https://www.dublincore.org/specifications/dublin-core/dcmi-terms/
*
* @var array|null
*/
protected $dcterms;
/**
* Interaction policy is an attempt to limit the harmful effects of unwanted replies and
* other interactions on a user's posts (e.g., "reply guys").
*
* It is also used by Mastodon to limit the ability to quote posts.
*
* @see https://docs.gotosocial.org/en/latest/federation/interaction_policy/
* @see https://blog.joinmastodon.org/2025/09/introducing-quote-posts/
*
* @var array|null
*/
protected $interaction_policy;
/**
* Fediverse Enhancement Proposal 044f: Quote Property
*
* @see https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md
* @see https://w3id.org/fep/044f#quote
*
* @var string|null
*/
protected $quote;
/**
* ActivityStreams quoteUrl property.
*
* @see https://www.w3.org/ns/activitystreams#quoteUrl
*
* @var string|null
*/
protected $quote_url;
/**
* Fedibird-specific quoteUri property.
*
* @see https://fedibird.com/ns#quoteUri
*
* @var string|null
*/
protected $quote_uri;
/**
* Misskey-specific quote property.
*
* @see https://misskey-hub.net/ns/#_misskey_quote
*
* @var string|null
*/
protected $_misskey_quote; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
/**
* Generic getter.
*

View File

@ -17,6 +17,10 @@ use function Activitypub\snake_to_camel_case;
* It is used to create objects that might be unknown by the plugin but
* conform to the ActivityStreams vocabulary.
*
* Provides generic magic methods for getting, setting, and adding properties
* through __call(). Specific property documentation is in the classes where
* the properties are actually defined.
*
* @since 5.3.0
*/
#[\AllowDynamicProperties]
@ -62,6 +66,8 @@ class Generic_Object {
*
* @param string $method The method name.
* @param string $params The method params.
*
* @return mixed
*/
public function __call( $method, $params ) {
$var = \strtolower( \substr( $method, 4 ) );
@ -81,6 +87,8 @@ class Generic_Object {
if ( \strncasecmp( $method, 'add', 3 ) === 0 ) {
return $this->add( $var, $params[0] );
}
return null;
}
/**
@ -114,7 +122,7 @@ class Generic_Object {
* @param string $key The key to set.
* @param mixed $value The value to add.
*
* @return mixed The value.
* @return mixed|void The value.
*/
public function add( $key, $value ) {
if ( empty( $value ) ) {
@ -158,7 +166,7 @@ class Generic_Object {
*
* @param string $json The JSON string.
*
* @return Generic_Object|\WP_Error An Object built from the JSON string or WP_Error when it's not a JSON string.
* @return static|\WP_Error An Object built from the JSON string or WP_Error when it's not a JSON string.
*/
public static function init_from_json( $json ) {
$array = \json_decode( $json, true );
@ -175,7 +183,7 @@ class Generic_Object {
*
* @param array $data The object array.
*
* @return Generic_Object|\WP_Error An Object built from the input array or WP_Error when it's not an array.
* @return static|\WP_Error An Object built from the input array or WP_Error when it's not an array.
*/
public static function init_from_array( $data ) {
if ( ! is_array( $data ) ) {
@ -196,7 +204,11 @@ class Generic_Object {
public function from_array( $data ) {
foreach ( $data as $key => $value ) {
if ( null !== $value ) {
$key = camel_to_snake_case( $key );
// Convert camelCase to snake_case if not prefixed with '_'.
if ( ! \str_starts_with( $key, '_' ) ) {
$key = camel_to_snake_case( $key );
}
call_user_func( array( $this, 'set_' . $key ), $value );
}
}
@ -219,11 +231,18 @@ class Generic_Object {
* It tries to get the object attributes if they exist
* and falls back to the getters. Empty values are ignored.
*
* By default, `bto` and `bcc` (the blind audience fields) are stripped
* from the output per ActivityPub Section 6, so every serialization path
* is safe for emission. Internal callers that need to persist the blind
* audience (e.g., outbox/inbox storage) can opt in by passing
* `$include_blind_audience = true`.
*
* @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true.
* @param bool $include_blind_audience Whether to keep `bto` and `bcc` in the output. Default false.
*
* @return array An array built from the Object.
*/
public function to_array( $include_json_ld_context = true ) {
public function to_array( $include_json_ld_context = true, $include_blind_audience = false ) {
$array = array();
$vars = get_object_vars( $this );
@ -243,11 +262,14 @@ class Generic_Object {
}
if ( is_object( $value ) ) {
$value = $value->to_array( false );
$value = $value->to_array( false, $include_blind_audience );
}
// If value is still empty, ignore it for the array and continue.
if ( isset( $value ) ) {
if ( is_array( $value ) && $this->is_namespaced( $key ) ) {
foreach ( $value as $sub_key => $sub_value ) {
$array[ snake_to_camel_case( $key ) . ':' . snake_to_camel_case( $sub_key ) ] = $sub_value;
}
} elseif ( isset( $value ) ) {
$array[ snake_to_camel_case( $key ) ] = $value;
}
}
@ -281,18 +303,33 @@ class Generic_Object {
*
* @return array The filtered array of the ActivityPub object.
*/
return \apply_filters( "activitypub_activity_{$class}_object_array", $array, $this->id, $this );
$array = \apply_filters( "activitypub_activity_{$class}_object_array", $array, $this->id, $this );
if ( ! $include_blind_audience ) {
/*
* Strip `bto` and `bcc` from the serialized array per ActivityPub Section 6.
* Callers that need the blind audience either read it from the object via
* `get_bto()` / `get_bcc()` or opt in with `$include_blind_audience = true`.
*/
unset( $array['bto'], $array['bcc'] );
if ( isset( $array['object'] ) && \is_array( $array['object'] ) ) {
unset( $array['object']['bto'], $array['object']['bcc'] );
}
}
return $array;
}
/**
* Convert Object to JSON.
*
* @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true.
* @param bool $include_blind_audience Whether to keep `bto` and `bcc` in the output. Default false.
*
* @return string The JSON string.
*/
public function to_json( $include_json_ld_context = true ) {
$array = $this->to_array( $include_json_ld_context );
public function to_json( $include_json_ld_context = true, $include_blind_audience = false ) {
$array = $this->to_array( $include_json_ld_context, $include_blind_audience );
$options = \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT | \JSON_UNESCAPED_SLASHES;
/**
@ -322,4 +359,23 @@ class Generic_Object {
public function get_json_ld_context() {
return static::JSON_LD_CONTEXT;
}
/**
* Checks if an attribute is in a namespace.
*
* @param string $attribute The attribute to check.
*
* @return bool Whether the attribute is namespaced.
*/
private function is_namespaced( $attribute ) {
$namespaces = array();
foreach ( static::JSON_LD_CONTEXT as $context ) {
if ( is_array( $context ) ) {
$namespaces = \array_merge( $namespaces, $context );
}
}
return isset( $namespaces[ $attribute ] ) && \wp_http_validate_url( $namespaces[ $attribute ] );
}
}

View File

@ -0,0 +1,5 @@
# Extended Objects
This folder contains more complex ActivityPub objects.
Although they could be created using the `Base_Object`, they provide an easier structure for creating objects with maximum compatibility.

View File

@ -10,11 +10,47 @@ namespace Activitypub\Activity\Extended_Object;
use Activitypub\Activity\Base_Object;
/**
* Event is an implementation of one of the Activity Streams Event object type.
* Event is an implementation of Activity Streams Event object type.
*
* This class contains extra keys as used by Mobilizon to ensure compatibility.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event
*
* @method string|null get_actor() Gets which actor created the event.
* @method float|null get_altitude() Gets the altitude of the event location.
* @method bool|null get_anonymous_participation_enabled() Gets whether anonymous participation is enabled.
* @method string|null get_category() Gets the event's category.
* @method bool|null get_comments_enabled() Gets whether comments/replies are enabled.
* @method array|null get_contacts() Gets the event's contacts.
* @method string|null get_external_participation_url() Gets the external participation URL.
* @method string|null get_in_language() Gets the language of the event.
* @method bool|null get_is_online() Gets whether the event is online.
* @method string|null get_join_mode() Gets how new members may be able to join.
* @method int|null get_maximum_attendee_capacity() Gets how many places there can be for an event.
* @method string|null get_name() Gets the title of the event.
* @method int|null get_participant_count() Gets the participant count of the event.
* @method int|null get_remaining_attendee_capacity() Gets the number of attendee places that remain unallocated.
* @method string|null get_replies_moderation_option() Gets the moderation option for replies.
* @method string|null get_status() Gets the event's status.
* @method string|null get_timezone() Gets the timezone of the event.
*
* @method Event set_actor( string $actor ) Sets which actor created the event.
* @method Event set_altitude( float $altitude ) Sets the altitude of the event location.
* @method Event set_anonymous_participation_enabled( bool $enabled ) Sets whether anonymous participation is enabled.
* @method Event set_category( string $category, bool $mobilizon_compatibility ) Sets the event's category.
* @method Event set_comments_enabled( bool $comments_enabled ) Sets whether comments/replies are enabled.
* @method Event set_contacts( array $contacts ) Sets the event's contacts.
* @method Event set_external_participation_url( string $url ) Sets the external participation URL.
* @method Event set_in_language( string $language ) Sets the language of the event.
* @method Event set_is_online( bool $is_online ) Sets whether the event is online.
* @method Event set_join_mode( string $join_mode ) Sets how new members may be able to join.
* @method Event set_maximum_attendee_capacity( int $capacity ) Sets how many places there can be for an event.
* @method Event set_name( string $name ) Sets the title of the event.
* @method Event set_participant_count( int $count ) Sets the participant count of the event.
* @method Event set_remaining_attendee_capacity( int $capacity ) Sets the number of attendee places that remain unallocated.
* @method Event set_replies_moderation_option( string $type ) Sets the moderation option for replies.
* @method Event set_status( string $status ) Sets the event's status.
* @method Event set_timezone( string $timezone ) Sets the timezone of the event.
*/
class Event extends Base_Object {
// Human friendly minimal context for full Mobilizon compatible ActivityPub events.
@ -123,7 +159,7 @@ class Event extends Base_Object {
protected $name;
/**
* The events contacts.
* The event's contacts.
*
* @context {
* '@id' => 'mz:contacts',

View File

@ -11,13 +11,27 @@ namespace Activitypub\Activity\Extended_Object;
use Activitypub\Activity\Base_Object;
/**
* Event is an implementation of one of the
* Activity Streams Event object type
* Place is an implementation of the Activity Streams Place object type.
*
* The Object is the primary base type for the Activity Streams
* vocabulary.
* The Place object represents a logical or physical location.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place
*
* @method float|null get_accuracy() Gets the accuracy of position coordinates.
* @method array|string|null get_address() Gets the address of the place.
* @method float|null get_altitude() Gets the altitude of the place.
* @method float|null get_latitude() Gets the latitude of the place.
* @method float|null get_longitude() Gets the longitude of the place.
* @method float|null get_radius() Gets the radius from the given latitude and longitude.
* @method string|null get_units() Gets the measurement units for radius and altitude.
*
* @method Place set_accuracy( float $accuracy ) Sets the accuracy of position coordinates.
* @method Place set_address( array|string $address ) Sets the address of the place.
* @method Place set_altitude( float $altitude ) Sets the altitude of the place.
* @method Place set_latitude( float $latitude ) Sets the latitude of the place.
* @method Place set_longitude( float $longitude ) Sets the longitude of the place.
* @method Place set_radius( float $radius ) Sets the radius from the given latitude and longitude.
* @method Place set_units( string $units ) Sets the measurement units for radius and altitude.
*/
class Place extends Base_Object {
/**

View File

@ -0,0 +1,70 @@
<?php
/**
* Quote_Authorization is an implementation of the QuoteAuthorization activity type,
* as defined in FEP-044f (https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md#quoteauthorization).
*
* This class represents a QuoteAuthorization activity for ActivityPub implementations.
*
* @package Activitypub
*/
namespace Activitypub\Activity\Extended_Object;
use Activitypub\Activity\Base_Object;
/**
* Class representing a QuoteAuthorization activity.
*
* @see https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md#quoteauthorization
*
* @since 7.5.0
*
* @method Base_Object|string|array|null get_interacting_object() Gets the interacting object property of the object.
* @method Base_Object|string|array|null get_interaction_target() Gets the interaction target property of the object.
*
* @method Quote_Authorization set_interacting_object( string|array|Base_Object|null $data ) Sets the interacting object property of the object.
* @method Quote_Authorization set_interaction_target( string|array|Base_Object|null $data ) Sets the interaction target property of the object.
*/
class Quote_Authorization extends Base_Object {
/**
* The JSON-LD context for the object.
*
* @var array
*/
const JSON_LD_CONTEXT = array(
'https://www.w3.org/ns/activitystreams',
array(
'QuoteAuthorization' => 'https://w3id.org/fep/044f#QuoteAuthorization',
'gts' => 'https://gotosocial.org/ns#',
'interactingObject' => array(
'@id' => 'gts:interactingObject',
'@type' => '@id',
),
'interactionTarget' => array(
'@id' => 'gts:interactionTarget',
'@type' => '@id',
),
),
);
/**
* The type of the object.
*
* @var string
*/
protected $type = 'QuoteAuthorization';
/**
* The object that is being interacted with.
*
* @var Base_Object|string|array|null
*/
protected $interacting_object;
/**
* The target of the interaction.
*
* @var Base_Object|string|array|null
*/
protected $interaction_target;
}