WIP: Rewrite of transformer management
Some checks are pending
PHP_CodeSniffer / phpcs (push) Waiting to run
Unit Testing / phpunit (5.6, 6.2) (push) Waiting to run
Unit Testing / phpunit (7.0) (push) Waiting to run
Unit Testing / phpunit (7.2) (push) Waiting to run
Unit Testing / phpunit (7.3) (push) Waiting to run
Unit Testing / phpunit (7.4) (push) Waiting to run
Unit Testing / phpunit (8.0) (push) Waiting to run
Unit Testing / phpunit (8.1) (push) Waiting to run
Unit Testing / phpunit (8.2) (push) Waiting to run
Unit Testing / phpunit (latest) (push) Waiting to run
Some checks are pending
PHP_CodeSniffer / phpcs (push) Waiting to run
Unit Testing / phpunit (5.6, 6.2) (push) Waiting to run
Unit Testing / phpunit (7.0) (push) Waiting to run
Unit Testing / phpunit (7.2) (push) Waiting to run
Unit Testing / phpunit (7.3) (push) Waiting to run
Unit Testing / phpunit (7.4) (push) Waiting to run
Unit Testing / phpunit (8.0) (push) Waiting to run
Unit Testing / phpunit (8.1) (push) Waiting to run
Unit Testing / phpunit (8.2) (push) Waiting to run
Unit Testing / phpunit (latest) (push) Waiting to run
This commit is contained in:
parent
b744dc551d
commit
6c6d9076a8
12 changed files with 743 additions and 12 deletions
|
@ -26,6 +26,9 @@ use function Activitypub\snake_to_camel_case;
|
||||||
* @see https://www.w3.org/TR/activitystreams-core/#object
|
* @see https://www.w3.org/TR/activitystreams-core/#object
|
||||||
*/
|
*/
|
||||||
class Base_Object {
|
class Base_Object {
|
||||||
|
const CONTEXT_ACTIVITYSTREAMS = 'https://www.w3.org/ns/activitystreams';
|
||||||
|
const CONTEXT_SECURITY = 'https://w3id.org/security/v1';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The object's unique global identifier
|
* The object's unique global identifier
|
||||||
*
|
*
|
||||||
|
@ -457,7 +460,7 @@ class Base_Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( \strncasecmp( $method, 'set', 3 ) === 0 ) {
|
if ( \strncasecmp( $method, 'set', 3 ) === 0 ) {
|
||||||
$this->set( $var, $params[0] );
|
return $this->set( $var, $params[0] );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( \strncasecmp( $method, 'add', 3 ) === 0 ) {
|
if ( \strncasecmp( $method, 'add', 3 ) === 0 ) {
|
||||||
|
@ -465,6 +468,13 @@ class Base_Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ActivityPub object typicallly can define it's own JSON-LD context.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->context = $this->get_context();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magic function, to transform the object to string.
|
* Magic function, to transform the object to string.
|
||||||
*
|
*
|
||||||
|
@ -506,6 +516,9 @@ class Base_Object {
|
||||||
* @return boolean True if the object has the key.
|
* @return boolean True if the object has the key.
|
||||||
*/
|
*/
|
||||||
public function has( $key ) {
|
public function has( $key ) {
|
||||||
|
if ( $key === 'actor ') {
|
||||||
|
$key = 'actor';
|
||||||
|
}
|
||||||
return property_exists( $this, $key );
|
return property_exists( $this, $key );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,12 +532,16 @@ class Base_Object {
|
||||||
*/
|
*/
|
||||||
public function set( $key, $value ) {
|
public function set( $key, $value ) {
|
||||||
if ( ! $this->has( $key ) ) {
|
if ( ! $this->has( $key ) ) {
|
||||||
|
if ( $key === 'actor' ) {
|
||||||
|
$key = 'actor';
|
||||||
|
}
|
||||||
return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
|
return new WP_Error( 'invalid_key', __( 'Invalid key', 'activitypub' ), array( 'status' => 404 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$this->$key = $value;
|
$this->$key = $value;
|
||||||
|
|
||||||
return $this->$key;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -692,4 +709,110 @@ class Base_Object {
|
||||||
public function get_object_var_keys() {
|
public function get_object_var_keys() {
|
||||||
return \array_keys( \get_object_vars( $this ) );
|
return \array_keys( \get_object_vars( $this ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the context information for a property.
|
||||||
|
*
|
||||||
|
* @param string $property
|
||||||
|
*
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
private function get_property_context( string $property ) {
|
||||||
|
$reflection_class = new \ReflectionClass( $this );
|
||||||
|
|
||||||
|
if ( $reflection_class->hasProperty( $property ) ) {
|
||||||
|
$reflection_property = $reflection_class->getProperty( $property );
|
||||||
|
$doc_omment = $reflection_property->getDocComment();
|
||||||
|
|
||||||
|
// Extract context information from the doc comment.
|
||||||
|
preg_match( '/@context\s+([^\s]+)/', $doc_omment, $matches );
|
||||||
|
|
||||||
|
if ( ! empty( $matches[1] ) ) {
|
||||||
|
return $matches[1];
|
||||||
|
} else {
|
||||||
|
return self::CONTEXT_ACTIVITYSTREAMS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compact the context via the JSON-LD syntax.
|
||||||
|
*
|
||||||
|
* @param array $key_context A certain part of the whole context.
|
||||||
|
* @param array $array The full URIs of the contexts.
|
||||||
|
* @param array $abbreviation The short name of the context.
|
||||||
|
*
|
||||||
|
* @return array $key_kontext The compacted context.
|
||||||
|
*/
|
||||||
|
private static function compact_context( $key_context, $namespace, $abbreviation ) {
|
||||||
|
$abbreviation_added = false;
|
||||||
|
foreach ( $key_context as $key => $value ) {
|
||||||
|
// Check if the key starts with the namespace
|
||||||
|
if ( strpos( $value, $namespace ) === 0 ) {
|
||||||
|
// Replace the key
|
||||||
|
$key_context[ $key ] = $abbreviation . ':' . substr( $value, strlen( $namespace ) );
|
||||||
|
|
||||||
|
// Add abbreviation element for the namespace only once
|
||||||
|
if ( ! $abbreviation_added ) {
|
||||||
|
$key_context = array( $abbreviation => $namespace ) + $key_context;
|
||||||
|
$abbreviation_added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $key_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the context of the ActivityPub object via the PHP docs.
|
||||||
|
*
|
||||||
|
* @return array $context A shortened and clean JSON-LD context for the ActivityPub object.
|
||||||
|
*/
|
||||||
|
public static function get_context() {
|
||||||
|
$class = static::class;
|
||||||
|
|
||||||
|
// Try to lookup the context from a transient.
|
||||||
|
$transient = "activitypub_json_context_object_{$class}";
|
||||||
|
$context = get_transient( $transient );
|
||||||
|
if ( $context ) {
|
||||||
|
return $context;
|
||||||
|
}
|
||||||
|
$reflection_class = new \ReflectionClass( static::class );
|
||||||
|
$context = array(
|
||||||
|
self::CONTEXT_ACTIVITYSTREAMS,
|
||||||
|
self::CONTEXT_SECURITY,
|
||||||
|
);
|
||||||
|
|
||||||
|
$key_context = array();
|
||||||
|
|
||||||
|
foreach ( $reflection_class->getProperties() as $property ) {
|
||||||
|
$doc_omment = $property->getDocComment();
|
||||||
|
|
||||||
|
// Extract context information from the doc comment.
|
||||||
|
preg_match( '/@context\s+([^\s]+)/', $doc_omment, $matches );
|
||||||
|
|
||||||
|
if ( ! empty( $matches[1] ) ) {
|
||||||
|
$key_context[ snake_to_camel_case( $property->name ) ] = $matches[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$namespace_abbreviations = array(
|
||||||
|
'https://joinpeertube.org/ns#' => 'pt',
|
||||||
|
'https://joinmobilizon.org/ns#' => 'mz',
|
||||||
|
'https://schema.org/' => 'sc',
|
||||||
|
'https://www.w3.org/2002/12/cal/ical#' => 'ical',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ( $namespace_abbreviations as $namespace => $abbreviation ) {
|
||||||
|
$key_context = self::compact_context( $key_context, $namespace, $abbreviation );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! empty( $key_context ) ) {
|
||||||
|
$context[] = $key_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_transient( $transient, $context );
|
||||||
|
return $context;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
128
includes/activity/class-event.php
Normal file
128
includes/activity/class-event.php
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ActivityPub Object of type Event.
|
||||||
|
*
|
||||||
|
* @package activity-event-transformers
|
||||||
|
* @license AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Activitypub\Activity;
|
||||||
|
|
||||||
|
use Activitypub\Activity\Base_Object;
|
||||||
|
|
||||||
|
use function Activitypub\snake_to_camel_case;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event is an implementation of one of the 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
|
||||||
|
*/
|
||||||
|
class Event extends Base_Object {
|
||||||
|
// todo maybe rename to mobilizon event?
|
||||||
|
const REPLIES_MODERATION_OPTION_TYPES = array( 'allow_all', 'closed' );
|
||||||
|
const JOIN_MODE_TYPES = array( 'free', 'restricted', 'external' ); // amd 'invite', but not used by mobilizon atm
|
||||||
|
const ICAL_EVENT_STATUS_TYPES = array( 'TENTATIVE', 'CONFIRMED', 'CANCELLED' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event is an implementation of one of the
|
||||||
|
* Activity Streams
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $type = 'Event';
|
||||||
|
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
protected $contacts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension invented by PeerTube whether comments/replies are <enabled>
|
||||||
|
* Mobilizon also implemented this as a fallback to their own
|
||||||
|
* repliesModerationOption.
|
||||||
|
*
|
||||||
|
* @context https://joinpeertube.org/ns#commentsEnabled
|
||||||
|
* @see https://docs.joinpeertube.org/api/activitypub#video
|
||||||
|
* @see https://docs.joinmobilizon.org/contribute/activity_pub/
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
protected $comments_enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://joinmobilizon.org/ns#timezone
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $timezone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://joinmobilizon.org/ns#repliesModerationOption
|
||||||
|
* @see https://docs.joinmobilizon.org/contribute/activity_pub/#repliesmoderation
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $replies_moderation_option;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://joinmobilizon.org/ns#anonymousParticipationEnabled
|
||||||
|
* @see https://docs.joinmobilizon.org/contribute/activity_pub/#anonymousparticipationenabled
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $anonymous_participation_enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://schema.org/category
|
||||||
|
* @var enum
|
||||||
|
*/
|
||||||
|
protected $category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://schema.org/inLanguage
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
|
protected $in_language;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://joinmobilizon.org/ns#isOnline
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $is_online;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://www.w3.org/2002/12/cal/ical#status
|
||||||
|
* @var enum
|
||||||
|
*/
|
||||||
|
protected $status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://joinmobilizon.org/ns#externalParticipationUrl
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $external_participation_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://joinmobilizon.org/ns#joinMode
|
||||||
|
* @see https://docs.joinmobilizon.org/contribute/activity_pub/#joinmode
|
||||||
|
* @var
|
||||||
|
*/
|
||||||
|
protected $join_mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://joinmobilizon.org/ns#participantCount
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $participant_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://schema.org/maximumAttendeeCapacity
|
||||||
|
* @see https://docs.joinmobilizon.org/contribute/activity_pub/#maximumattendeecapacity
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $maximum_attendee_capacity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @context https://schema.org/remainingAttendeeCapacity
|
||||||
|
* @see https://docs.joinmobilizon.org/contribute/activity_pub/#remainignattendeecapacity
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $remaining_attendee_capacity;
|
||||||
|
}
|
94
includes/activity/class-place.php
Normal file
94
includes/activity/class-place.php
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Event is an implementation of one of the
|
||||||
|
* Activity Streams Event object type
|
||||||
|
*
|
||||||
|
* @package activity-event-transformers
|
||||||
|
* @license AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Activitypub\Activity;
|
||||||
|
|
||||||
|
use Activitypub\Activity\Base_Object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event is an implementation of one of the
|
||||||
|
* Activity Streams Event object type
|
||||||
|
*
|
||||||
|
* The Object is the primary base type for the Activity Streams
|
||||||
|
* vocabulary.
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event
|
||||||
|
*/
|
||||||
|
class Place extends Base_Object {
|
||||||
|
/**
|
||||||
|
* Place is an implementation of one of the
|
||||||
|
* Activity Streams
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $type = 'Place';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the accuracy of position coordinates on a Place objects.
|
||||||
|
* Expressed in properties of percentage. e.g. "94.0" means "94.0% accurate".
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accuracy
|
||||||
|
* @var float xsd:float [>= 0.0f, <= 100.0f]
|
||||||
|
*/
|
||||||
|
protected $accuracy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the altitude of a place. The measurement units is indicated using the units property.
|
||||||
|
* If units is not specified, the default is assumed to be "m" indicating meters.
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-altitude
|
||||||
|
* @var float xsd:float
|
||||||
|
*/
|
||||||
|
protected $altitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The latitude of a place.
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-latitude
|
||||||
|
* @var float xsd:float
|
||||||
|
*/
|
||||||
|
protected $latitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The longitude of a place.
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-longitude
|
||||||
|
* @var float xsd:float
|
||||||
|
*/
|
||||||
|
protected $longitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-radius
|
||||||
|
* @var float
|
||||||
|
*/
|
||||||
|
protected $radius;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-units
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $units;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension invented by PeerTube whether comments/replies are <enabled>
|
||||||
|
* Mobilizon also implemented this as a fallback to their own
|
||||||
|
* repliesModerationOption.
|
||||||
|
*
|
||||||
|
* @see https://docs.joinpeertube.org/api/activitypub#video
|
||||||
|
* @see https://docs.joinmobilizon.org/contribute/activity_pub/
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $comments_enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Postal_Address|string
|
||||||
|
*/
|
||||||
|
protected $address;
|
||||||
|
}
|
62
includes/activity/class-postal-address.php
Normal file
62
includes/activity/class-postal-address.php
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PostalAddress is a custom ActivityPub object firstly used by Mobilizon
|
||||||
|
* derived from https://schema.org/PostalAddress.
|
||||||
|
*
|
||||||
|
* @package activity-event-transformers
|
||||||
|
* @license AGPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Activitypub\Activity;
|
||||||
|
|
||||||
|
use Activitypub\Activity\Base_Object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event
|
||||||
|
*/
|
||||||
|
class Postal_Address extends Base_Object {
|
||||||
|
/**
|
||||||
|
* Place is an implementation of one of the
|
||||||
|
* Activity Streams
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $type = 'PostalAddress';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The country. For example, USA. You can also provide the two-letter ISO 3166-1 alpha-2 country code.
|
||||||
|
*
|
||||||
|
* @see http://en.wikipedia.org/wiki/ISO_3166-1
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $address_country;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The locality in which the street address is, and which is in the region. For example, Mountain View.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $address_locality;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The region in which the locality is, and which is in the country.
|
||||||
|
* For example, California or another appropriate first-level Administrative division.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $address_region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The postal code. For example, 94043.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $postal_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The street address. For example, 1600 Amphitheatre Pkwy.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $street_address;
|
||||||
|
}
|
|
@ -62,7 +62,7 @@ class Activity_Dispatcher {
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function send_activity( $wp_object, $type, $user_id = null ) {
|
public static function send_activity( $wp_object, $type, $user_id = null ) {
|
||||||
$transformer = Factory::get_transformer( $wp_object );
|
$transformer = Factory::instance()->get_transformer( $wp_object );
|
||||||
|
|
||||||
if ( null !== $user_id ) {
|
if ( null !== $user_id ) {
|
||||||
$transformer->change_wp_user_id( $user_id );
|
$transformer->change_wp_user_id( $user_id );
|
||||||
|
@ -106,7 +106,7 @@ class Activity_Dispatcher {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$transformer = Factory::get_transformer( $wp_object );
|
$transformer = Factory::instance()->get_transformer( $wp_object );
|
||||||
$transformer->change_wp_user_id( Users::BLOG_USER_ID );
|
$transformer->change_wp_user_id( Users::BLOG_USER_ID );
|
||||||
|
|
||||||
$user_id = $transformer->get_wp_user_id();
|
$user_id = $transformer->get_wp_user_id();
|
||||||
|
|
|
@ -197,4 +197,20 @@ class Migration {
|
||||||
wp_cache_delete( sprintf( Followers::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
|
wp_cache_delete( sprintf( Followers::CACHE_KEY_INBOXES, $user_id ), 'activitypub' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the supported post type settings to the mapped transformer setting.
|
||||||
|
* TODO: Test this
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function migrate_from_version_number_transformer_management_placeholder() {
|
||||||
|
$supported_post_types = \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) );
|
||||||
|
Admin::register_settings();
|
||||||
|
$transformer_mapping = array();
|
||||||
|
foreach ( $supported_post_types as $supported_post_type ) {
|
||||||
|
$transformer_mapping[ $supported_post_type ] = 'activitypub/post';
|
||||||
|
}
|
||||||
|
update_option( 'activitypub_transformer_mapping', $transformer_mapping );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,24 @@ use Activitypub\Transformer\Post;
|
||||||
* - Activitypub\Activity\Base_Object
|
* - Activitypub\Activity\Base_Object
|
||||||
*/
|
*/
|
||||||
class Attachment extends Post {
|
class Attachment extends Post {
|
||||||
|
/**
|
||||||
|
* Getter function for the name of the transformer.
|
||||||
|
*
|
||||||
|
* @return string name
|
||||||
|
*/
|
||||||
|
public function get_name() {
|
||||||
|
return 'activitypub/attachment';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter function for the display name (label/title) of the transformer.
|
||||||
|
*
|
||||||
|
* @return string name
|
||||||
|
*/
|
||||||
|
public function get_label() {
|
||||||
|
return 'Built-In Transformer for WordPress Attachments';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates all Media Attachments for a Post.
|
* Generates all Media Attachments for a Post.
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,6 +18,8 @@ abstract class Base {
|
||||||
*/
|
*/
|
||||||
protected $object;
|
protected $object;
|
||||||
|
|
||||||
|
protected $activitypub_object_type = 'Base_Object';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static function to Transform a WordPress Object.
|
* Static function to Transform a WordPress Object.
|
||||||
*
|
*
|
||||||
|
@ -36,8 +38,10 @@ abstract class Base {
|
||||||
*
|
*
|
||||||
* @param stdClass $object
|
* @param stdClass $object
|
||||||
*/
|
*/
|
||||||
public function __construct( $object ) {
|
public function __construct( $object=null ) {
|
||||||
$this->object = $object;
|
if ( $object ) {
|
||||||
|
$this->object = $object;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,4 +106,30 @@ abstract class Base {
|
||||||
* @return int The User-ID of the WordPress Post
|
* @return int The User-ID of the WordPress Post
|
||||||
*/
|
*/
|
||||||
abstract public function change_wp_user_id( $user_id );
|
abstract public function change_wp_user_id( $user_id );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name used for registering the transformer with the ActivityPub plugin.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @return string name
|
||||||
|
*/
|
||||||
|
abstract public function get_name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the display name for the ActivityPub transformer.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @return string display name
|
||||||
|
*/
|
||||||
|
abstract public function get_label();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ActivityStreams 2.0 Object-Type for a Post.
|
||||||
|
*
|
||||||
|
* @see https://www.w3.org/TR/activitystreams-vocabulary/#activity-types
|
||||||
|
*
|
||||||
|
* @return string The Object-Type.
|
||||||
|
*/
|
||||||
|
abstract protected function get_object_type();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,214 @@ use Activitypub\Transformer\Attachment;
|
||||||
* Transformer Factory
|
* Transformer Factory
|
||||||
*/
|
*/
|
||||||
class Factory {
|
class Factory {
|
||||||
public static function get_transformer( $object ) {
|
const DEFAULT_TRANSFORMER_MAPPING = array(
|
||||||
|
'post' => 'activitypub/post',
|
||||||
|
'page' => 'activitypub/post',
|
||||||
|
'attachment' => 'activitypub/attachment',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformers.
|
||||||
|
*
|
||||||
|
* Holds the list of all the ActivityPub transformers. Default is `null`.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @access private
|
||||||
|
*
|
||||||
|
* @var \ActivityPub\Transformer\Base[]
|
||||||
|
*/
|
||||||
|
private $transformers = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* F instance.
|
||||||
|
*
|
||||||
|
* Holds the transformer instance.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
protected static $_instances = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance.
|
||||||
|
*
|
||||||
|
* Ensures only one instance of the transformer manager class is loaded or can be loaded.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
*
|
||||||
|
* @return Transformer_Manager An instance of the class.
|
||||||
|
*/
|
||||||
|
public static function instance() {
|
||||||
|
$class_name = static::class_name();
|
||||||
|
|
||||||
|
if ( empty( static::$_instances[ $class_name ] ) ) {
|
||||||
|
static::$_instances[ $class_name ] = new static();
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::$_instances[ $class_name ];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class name.
|
||||||
|
*
|
||||||
|
* Retrieve the name of the class.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @access public
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
public static function class_name() {
|
||||||
|
return get_called_class();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a transformer is registered.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
*
|
||||||
|
* @param string $name Transformer name including namespace.
|
||||||
|
* @return bool True if the block type is registered, false otherwise.
|
||||||
|
*/
|
||||||
|
public function is_registered( $name ) {
|
||||||
|
return isset( $this->transformers[ $name ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a transformer.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @access public
|
||||||
|
*
|
||||||
|
* @param \ActivityPub\Transformer\Base $transformer_instance ActivityPub Transformer.
|
||||||
|
*
|
||||||
|
* @return bool True if the ActivityPub transformer was registered.
|
||||||
|
*/
|
||||||
|
public function register( \ActivityPub\Transformer\Base $transformer_instance ) {
|
||||||
|
|
||||||
|
if ( ! $transformer_instance instanceof \ActivityPub\Transformer\Base ) {
|
||||||
|
_doing_it_wrong(
|
||||||
|
__METHOD__,
|
||||||
|
\esc_html__( 'ActivityPub transformer instance must be a of \ActivityPub\Transformer_Base class.' ),
|
||||||
|
'version_number_transformer_management_placeholder'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$transformer_name = $transformer_instance->get_name();
|
||||||
|
if ( preg_match( '/[A-Z]+/', $transformer_name ) ) {
|
||||||
|
_doing_it_wrong(
|
||||||
|
__METHOD__,
|
||||||
|
\esc_html__( 'ActivityPub transformer names must not contain uppercase characters.' ),
|
||||||
|
'version_number_transformer_management_placeholder'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name_matcher = '/^[a-z0-9-]+\/[a-z0-9-]+$/';
|
||||||
|
if ( ! preg_match( $name_matcher, $transformer_name ) ) {
|
||||||
|
_doing_it_wrong(
|
||||||
|
__METHOD__,
|
||||||
|
\esc_html__( 'ActivityPub transformer names must contain a namespace prefix. Example: my-plugin/my-custom-transformer' ),
|
||||||
|
'version_number_transformer_management_placeholder'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $this->is_registered( $transformer_name ) ) {
|
||||||
|
_doing_it_wrong(
|
||||||
|
__METHOD__,
|
||||||
|
/* translators: %s: Block name. */
|
||||||
|
sprintf( 'ActivityPub transformer with name "%s" is already registered.', esc_html( $transformer_name ) ),
|
||||||
|
'version_number_transformer_management_placeholder'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the ActivityPub transformer be registered.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
*
|
||||||
|
* @param bool $should_register Should the ActivityPub transformer be registered. Default is `true`.
|
||||||
|
* @param \ActivityPub\Transformer\Base $transformer_instance Widget instance.
|
||||||
|
*/
|
||||||
|
$should_register = apply_filters( 'activitypub_transformer_is_enabled', true, $transformer_instance );
|
||||||
|
|
||||||
|
if ( ! $should_register ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->transformers[ $transformer_name ] = $transformer_instance;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init transformers.
|
||||||
|
*
|
||||||
|
* Initialize ActivityPub transformer manager.
|
||||||
|
* Include the builtin transformers by default and add third party ones.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
private function init_transformers() {
|
||||||
|
$builtin_transformers = [
|
||||||
|
'post',
|
||||||
|
'attachment'
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->transformers = [];
|
||||||
|
|
||||||
|
foreach ( $builtin_transformers as $transformer_name ) {
|
||||||
|
$class_name = ucfirst( $transformer_name );
|
||||||
|
|
||||||
|
$class_name = '\Activitypub\Transformer\\' . $class_name;
|
||||||
|
|
||||||
|
$this->register( new $class_name() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Let other transformers register.
|
||||||
|
*
|
||||||
|
* Fires after the built-in Activitypub transformers are registered.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
*
|
||||||
|
* @param Transformer_Factory $this The widgets manager.
|
||||||
|
*/
|
||||||
|
do_action( 'activitypub_transformers_register', $this );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get available ActivityPub transformers.
|
||||||
|
*
|
||||||
|
* Retrieve the registered transformers list. If given a transformer name
|
||||||
|
* it returns the given transformer if it is registered.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @access public
|
||||||
|
*
|
||||||
|
* @param string $transformer_name Optional. Transformer name. Default is null.
|
||||||
|
*
|
||||||
|
* @return Base|Base[]|null Registered transformers.
|
||||||
|
*/
|
||||||
|
public function get_transformer_class( $transformer_name = null ) {
|
||||||
|
if ( is_null( $this->transformers ) ) {
|
||||||
|
$this->init_transformers();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( null !== $transformer_name ) {
|
||||||
|
return isset( $this->transformers[ $transformer_name ] ) ? $this->transformers[ $transformer_name ] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->transformers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get_default_transformer( $object ) {
|
||||||
/**
|
/**
|
||||||
* Filter the transformer for a given object.
|
* Filter the transformer for a given object.
|
||||||
*
|
*
|
||||||
|
@ -58,4 +265,40 @@ class Factory {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mapped ActivityPub transformer.
|
||||||
|
*
|
||||||
|
* Returns a new instance of the needed WordPress to ActivityPub transformer.
|
||||||
|
*
|
||||||
|
* @since version_number_transformer_management_placeholder
|
||||||
|
* @access public
|
||||||
|
*
|
||||||
|
* @param WP_Post|WP_Comment $object The WordPress Post/Comment.
|
||||||
|
*
|
||||||
|
* @return \ActivityPub\Transformer\Base|null Registered transformers.
|
||||||
|
*/
|
||||||
|
public function get_transformer( $object ) {
|
||||||
|
switch ( get_class( $object ) ) {
|
||||||
|
case 'WP_Post':
|
||||||
|
$post_type = get_post_type( $object );
|
||||||
|
$transformer_mapping = \get_option( 'activitypub_transformer_mapping', self::DEFAULT_TRANSFORMER_MAPPING );
|
||||||
|
$transformer_name = $transformer_mapping[ $post_type ];
|
||||||
|
if ( $transformer_name ) {
|
||||||
|
$transformer_class = $this->get_transformer_class( $transformer_name );
|
||||||
|
} else {
|
||||||
|
return self::get_default_transformer( $object );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $transformer_class ) {
|
||||||
|
return new $transformer_class( $object );
|
||||||
|
} else {
|
||||||
|
return self::get_default_transformer( $object );
|
||||||
|
}
|
||||||
|
case 'WP_Comment':
|
||||||
|
return new Comment( $object );
|
||||||
|
default:
|
||||||
|
self::get_default_transformer( $object );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,24 @@ use function Activitypub\site_supports_blocks;
|
||||||
* - Activitypub\Activity\Base_Object
|
* - Activitypub\Activity\Base_Object
|
||||||
*/
|
*/
|
||||||
class Post extends Base {
|
class Post extends Base {
|
||||||
|
/**
|
||||||
|
* Getter function for the name of the transformer.
|
||||||
|
*
|
||||||
|
* @return string name
|
||||||
|
*/
|
||||||
|
public function get_name() {
|
||||||
|
return 'activitypub/post';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter function for the display name (label/title) of the transformer.
|
||||||
|
*
|
||||||
|
* @return string name
|
||||||
|
*/
|
||||||
|
public function get_label() {
|
||||||
|
return 'Built-In Transformer for WordPress Posts';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ID of the WordPress Post.
|
* Returns the ID of the WordPress Post.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
$comment = \get_comment( \get_query_var( 'c', null ) ); // phpcs:ignore
|
$comment = \get_comment( \get_query_var( 'c', null ) ); // phpcs:ignore
|
||||||
|
|
||||||
$object = \Activitypub\Transformer\Factory::get_transformer( $comment );
|
$object = \Activitypub\Transformer\Factory::instance()->get_transformer( $comment );
|
||||||
$json = \array_merge( array( '@context' => \Activitypub\get_context() ), $object->to_object()->to_array() );
|
$json = \array_merge( array( '@context' => \Activitypub\get_context() ), $object->to_object()->to_array() );
|
||||||
|
|
||||||
// filter output
|
// filter output
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||||
$post = \get_post();
|
$post = \get_post();
|
||||||
|
|
||||||
$post_object = \Activitypub\Transformer\Factory::get_transformer( $post )->to_object();
|
$post_object = \Activitypub\Transformer\Factory::instance()->get_transformer( $post )->to_object();
|
||||||
$post_object->set_context( \Activitypub\get_context() );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Action triggerd prior to the ActivityPub profile being created and sent to the client
|
* Action triggerd prior to the ActivityPub profile being created and sent to the client
|
||||||
|
|
Loading…
Reference in a new issue