Files
laipower/wp-content/plugins/activitypub/includes/activity/class-activity.php

315 lines
9.3 KiB
PHP

<?php
/**
* Inspired by the PHP ActivityPub Library by @Landrok
*
* @link https://github.com/landrok/activitypub
*
* @package Activitypub
*/
namespace Activitypub\Activity;
use Activitypub\Activity\Extended_Object\Event;
use Activitypub\Activity\Extended_Object\Place;
/**
* \Activitypub\Activity\Activity implements the common
* attributes of an Activity.
*
* @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',
),
);
/**
* The default types for Activities.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#activity-types
*
* @var array
*/
const TYPES = array(
'Accept',
'Add',
'Announce',
'Arrive',
'Block',
'Create',
'Delete',
'Dislike',
'Follow',
'Flag',
'Ignore',
'Invite',
'Join',
'Leave',
'Like',
'Listen',
'Move',
'Offer',
'QuoteRequest', // @see https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md
'Read',
'Reject',
'Remove',
'TentativeAccept',
'TentativeReject',
'Travel',
'Undo',
'Update',
'View',
);
/**
* The type of the object.
*
* @var string
*/
protected $type = 'Activity';
/**
* Describes the direct object of the activity.
* For instance, in the activity "John added a movie to his
* wishlist", the object of the activity is the movie added.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object-term
*
* @var string|Base_Object|array|null
*/
protected $object;
/**
* Describes one or more entities that either performed or are
* expected to perform the activity.
* Any single activity can have multiple actors.
* The actor MAY be specified using an indirect Link.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-actor
*
* @var string|array
*/
protected $actor;
/**
* The indirect object, or target, of the activity.
* The precise meaning of the target is largely dependent on the
* type of action being described but will often be the object of
* the English preposition "to".
* For instance, in the activity "John added a movie to his
* wishlist", the target of the activity is John's wishlist.
* An activity can have more than one target.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-target
*
* @var string|array|null
*/
protected $target;
/**
* Describes the result of the activity.
* For instance, if a particular action results in the creation of
* a new resource, the result property can be used to describe
* that new resource.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-result
*
* @var string|Base_Object|null
*/
protected $result;
/**
* Identifies a Collection containing objects considered to be responses
* to this object.
* WordPress has a strong core system of approving replies. We only include
* approved replies here.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies
*
* @var array|null
*/
protected $replies;
/**
* An indirect object of the activity from which the
* activity is directed.
* The precise meaning of the origin is the object of the English
* preposition "from".
* For instance, in the activity "John moved an item to List B
* from List A", the origin of the activity is "List A".
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-origin
*
* @var string|array|null
*/
protected $origin;
/**
* One or more objects used (or to be used) in the completion of an
* Activity.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument
*
* @var string|array|null
*/
protected $instrument;
/**
* Set the object and copy Object properties to the Activity.
*
* Any to, bto, cc, bcc, and audience properties specified on the object
* MUST be copied over to the new "Create" activity by the server.
*
* @see https://www.w3.org/TR/activitypub/#object-without-create
*
* @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 ) ) {
if ( array_is_list( $data ) ) {
$object = array_map( array( $this, 'maybe_convert_to_object' ), $data );
} else {
$object = $this->maybe_convert_to_object( $data );
}
}
$this->set( 'object', $object );
$this->pre_fill_activity_from_object();
}
/**
* Fills the Activity with the specified activity object.
*/
public function pre_fill_activity_from_object() {
$object = $this->get_object();
// 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 `$object` is an object and copy some properties otherwise do nothing.
if ( ! is_object( $object ) ) {
return;
}
foreach ( array( 'to', 'bto', 'cc', 'bcc', 'audience' ) as $i ) {
$value = $object->get( $i );
if ( $value && ! $this->get( $i ) ) {
$this->set( $i, $value );
}
}
if ( $object->get_published() && ! $this->get_published() ) {
$this->set( 'published', $object->get_published() );
}
if ( $object->get_updated() && ! $this->get_updated() ) {
$this->set( 'updated', $object->get_updated() );
}
if ( $object->get_attributed_to() && ! $this->get_actor() ) {
$this->set( 'actor', $object->get_attributed_to() );
}
if ( $this->get_type() !== 'Announce' && $object->get_in_reply_to() && ! $this->get_in_reply_to() ) {
$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() ) {
$updated = $object->get_updated();
} elseif ( $object->get_published() ) {
$updated = $object->get_published();
} else {
$updated = time();
}
$this->set( 'id', $id . '#activity-' . strtolower( $this->get_type() ) . '-' . $updated );
}
}
/**
* The context of an Activity is usually just the context of the object it contains.
*
* @return array $context A compacted JSON-LD context.
*/
public function get_json_ld_context() {
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;'.
return $class::JSON_LD_CONTEXT;
}
}
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;
}
}