From f70bcec1fba49bd47b7ddfcc8e717de2763ca4b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Menrath?= Date: Fri, 22 Dec 2023 19:07:59 +0100 Subject: [PATCH] WIP --- activitypub-event-transformers.php | 17 +- activitypub/object/class-event.php | 224 -------------------- activitypub/object/class-place.php | 90 -------- activitypub/object/class-postal-address.php | 58 ----- activitypub/transformer/class-tribe.php | 93 ++------ activitypub/transformer/class-vs-event.php | 120 ++++------- 6 files changed, 74 insertions(+), 528 deletions(-) delete mode 100644 activitypub/object/class-event.php delete mode 100644 activitypub/object/class-place.php delete mode 100644 activitypub/object/class-postal-address.php diff --git a/activitypub-event-transformers.php b/activitypub-event-transformers.php index 46a6dd4..84df772 100644 --- a/activitypub-event-transformers.php +++ b/activitypub-event-transformers.php @@ -25,20 +25,27 @@ if ( ! defined( 'ABSPATH' ) ) { * Include fransformer class file and register the transformer class. * * @since 1.0.0 - * @param \Activitypub\Transformer\Transformer_Factory $transformers_manager ActivtiyPub transformers manager. + * @param \Activitypub\Transformer\Factory $factory ActivtiyPub transformers factory. * @return void */ -function register_event_transformers( $transformers_manager ) { +function register_event_transformers( $transformers_factory ) { require_once __DIR__ . '/activitypub/transformer/class-tribe.php'; - $transformers_manager->register( new \Tribe() ); + $transformers_factory->register( new \Tribe() ); require_once __DIR__ . '/activitypub/transformer/class-vs-event.php'; - $transformers_manager->register( new \VS_Event() ); + $transformers_factory->register( new \VS_Event() ); } add_action( 'activitypub_transformers_register', 'register_event_transformers' ); - +// Filter be object class +add_filter( 'activitypub_transformer', function( $transformer, $object, $object_class ) { + if ( $object->post_type === 'event' ) { + require_once __DIR__ . '/activitypub/transformer/class-vs-event.php'; + return new \VS_Event( $object ); + } + return $transformer; +}, 10, 3 ); // TODO Below here is temporary code needed to do local testing atm. diff --git a/activitypub/object/class-event.php b/activitypub/object/class-event.php deleted file mode 100644 index c21d8c1..0000000 --- a/activitypub/object/class-event.php +++ /dev/null @@ -1,224 +0,0 @@ - - * 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; - - - /** - * 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 'https://www.w3.org/ns/activitystreams'; - } - } - - return null; - } - - 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; - } - - public static function get_context() { - $class = self::class; - $transient = "activitypub_json_context_object_{$class}"; - $context = get_transient( $transient ); - // if ( $context ) { - // return $context; - // } - $reflection_class = new ReflectionClass( self::class ); - $context = array( - 'https://www.w3.org/ns/activitystreams', - 'https://w3id.org/security/v1', - ); - - $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 ); - } - - $context[] = $key_context; - - set_transient( $transient, $context ); - return $context; - } - - - /** - * When using this class we need to add some filters. - */ - public function __construct() { - // $class = strtolower( get_class( $this ) ); - // add_filter( "activitypub_activity_{$class}_object_array", [ $this, 'filter_object_array' ] ); - // add_filter( 'activitypub_json_context', [ $this, 'filter_json_context' ] ); - } -} diff --git a/activitypub/object/class-place.php b/activitypub/object/class-place.php deleted file mode 100644 index d18a942..0000000 --- a/activitypub/object/class-place.php +++ /dev/null @@ -1,90 +0,0 @@ -= 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 - * 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; -} diff --git a/activitypub/object/class-postal-address.php b/activitypub/object/class-postal-address.php deleted file mode 100644 index 1d6490d..0000000 --- a/activitypub/object/class-postal-address.php +++ /dev/null @@ -1,58 +0,0 @@ -tribe_event = tribe_get_event( $wp_post->ID ); - } + // /** + // * resolve the tribe metadata in the setter of wp_post. + // * + // * @param WP_Post $wp_post The WP_Post object. + // * @return void + // */ + // public function set_wp_post( WP_Post $wp_post ) { + // parent::set_wp_post( $wp_post ); + // $this->tribe_event = tribe_get_event( $wp_post->ID ); + // } /** * Get widget name. @@ -93,7 +97,7 @@ class Tribe extends \Activitypub\Transformer\Base { // todo make it possible that one event can have multiple categories? // using cat_slugs isn't 100% nice way to do this, don't know if it's a good idea - $categories = tribe_get_event_cat_slugs( $this->wp_post->ID ); + $categories = tribe_get_event_cat_slugs( $this->object->ID ); if ( count( $categories ) === 0 ) { return null; @@ -174,69 +178,4 @@ class Tribe extends \Activitypub\Transformer\Base { $venue->country ); // todo add checks that everything exists here (lol) } - - /** - * Transforms the VS Event WP_Post object to an ActivityPub Event Object. - * - * @see \Activitypub\Activity\Base_Object - * - * @return \Activitypub\Activity\Base_Object The ActivityPub Object. - */ - public function transform() { - $object = new Event(); - - // todo xsd:dateTime is probably nearly everywhere used, should it be default? - $this->set_timeformat( 'Y-m-d\TH:i:s\Z' ); - - // todo this looks very duplicated - $object->set_default_language_for_maps( $this->get_locale() ); - $object->set_in_language( $this->get_locale() ); - - $object - // set metadata - ->set_id( $this->get_id() ) - ->set_url( $this->get_url() ) - ->set_external_participation_url( $this->get_url() ) - ->set_comments_enabled( $this->get_comments_open() ) - ->set_replies_moderation_option( 'allow_all' ) // comment_status = open todo - - // set published and updated - ->set_published( $this->get_published() ) - ->if( $this->get_updated() > $this->get_published() ) - ->set_updated( $this->get_updated() ) - - // set author and location - ->set_attributed_to( $this->get_attributed_to() ) - ->set_location( $this->get_event_location()->to_array() ) - - // set content - ->set_name( $this->get_post_property( 'post_title' ) ) - ->set_content( $this->get_content() ) - ->set_summary( $this->get_post_meta( 'post_excerpt', true, $this->get_content() ) ) - ->set_attachment( $this->get_attachments() ) - - // set event metadata - ->set_start_time( $this->get_post_meta_time( '_EventStartDateUTC' ) ) - ->set_end_time( $this->get_post_meta_time( '_EventEndDateUTC' ) ) - // ->set_duration() // todo - ->set_status( $this->get_tribe_status() ) - ->set_join_mode( 'external' ) - - ->set_tag( $this->get_tags() ) // todo maybe rename to get_hashtags()? - ->set_category( $this->get_tribe_category() ) - - // set direkt addressants (to followers and mentions) - ->set_to( $this->get_followers_stream() ) - ->set_cc( $this->get_cc() ); - - // todo events that cost something? - // maybe a setting for custom tags for online mode - - // todo generator maybe - - $some_infos = $object->check_jsonld_completeness(); // just used for debugging - - assert( $object->get_type() === $this->get_object_type() ); - return $object; - } } diff --git a/activitypub/transformer/class-vs-event.php b/activitypub/transformer/class-vs-event.php index fbd36a6..9828346 100644 --- a/activitypub/transformer/class-vs-event.php +++ b/activitypub/transformer/class-vs-event.php @@ -6,11 +6,9 @@ * @license AGPL-3.0-or-later */ -require_once __DIR__ . '/../object/class-event.php'; - -use Activitypub\Activity\Base_Object; -use Place; -use function Activitypub\get_rest_url_by_path; +use Activitypub\Activity\Event; +use Activitypub\Activity\Place; +use Activitypub\Transformer\Post; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. @@ -21,7 +19,7 @@ if ( ! defined( 'ABSPATH' ) ) { * * @since 1.0.0 */ -class VS_Event extends \Activitypub\Transformer\Base { +class VS_Event extends Post { /** * Get widget name. * @@ -89,8 +87,16 @@ class VS_Event extends \Activitypub\Transformer\Base { /** * Get the end time from the events metadata. */ - private function get_end_time() { - $end_time = get_post_meta( $this->wp_post->ID, 'event-date', true ); + protected function get_end_time() { + $end_time = get_post_meta( $this->object->ID, 'event-date', true ); + return \gmdate( 'Y-m-d\TH:i:s\Z', $end_time ); + } + + /** + * Get the end time from the events metadata. + */ + protected function get_start_time() { + $end_time = get_post_meta( $this->object->ID, 'event-start-date', true ); return \gmdate( 'Y-m-d\TH:i:s\Z', $end_time ); } @@ -98,7 +104,7 @@ class VS_Event extends \Activitypub\Transformer\Base { * Get the event link from the events metadata. */ private function get_event_link() { - $event_link = get_post_meta( $this->wp_post->ID, 'event-link', true ); + $event_link = get_post_meta( $this->object->ID, 'event-link', true ); if ( $event_link ) { return array( 'type' => 'Link', @@ -112,8 +118,8 @@ class VS_Event extends \Activitypub\Transformer\Base { /** * Overrides/extends the get_attachments function to also add the event Link. */ - protected function get_attachments() { - $attachments = parent::get_attachments(); + protected function get_attachment() { + $attachments = parent::get_attachment(); $attachments[0]['type'] = 'Document'; $attachments[0]['name'] = 'Banner'; $event_link = $this->get_event_link(); @@ -123,85 +129,51 @@ class VS_Event extends \Activitypub\Transformer\Base { return $attachments; } + protected function get_replies_moderation_option() { + return 'allow_all'; + } + + protected function get_status() { + return 'CONFIRMED'; + } + /** - * Transforms the VS Event WP_Post object to an ActivityPub Event Object. + * Transform the WordPress Object into an ActivityPub Object. * - * @see \Activitypub\Activity\Base_Object - * - * @return \Activitypub\Activity\Base_Object The ActivityPub Object. + * @return Activitypub\Activity\Event */ - public function transform() { - // todo make tranform nicer - $context = Event::get_context(); - $object = new Event(); - $object - ->set_id( $this->get_id() ) - ->set_url( $this->get_url() ) - ->set_type( $this->get_object_type() ); + public function to_object() { + $object = new Event(); - $published = \strtotime( $this->wp_post->post_date_gmt ); + $vars = $object->get_object_var_keys(); - $object->set_published( \gmdate( 'Y-m-d\TH:i:s\Z', $published ) ); + foreach ( $vars as $var ) { + $getter = 'get_' . $var; - $updated = \strtotime( $this->wp_post->post_modified_gmt ); + if ( method_exists( $this, $getter ) ) { + $value = call_user_func( array( $this, $getter ) ); - if ( $updated > $published ) { - $object->set_updated( \gmdate( 'Y-m-d\TH:i:s\Z', $updated ) ); + if ( isset( $value ) ) { + $setter = 'set_' . $var; + + call_user_func( array( $object, $setter ), $value ); + } + } } - $object - ->set_attributed_to( $this->get_attributed_to() ) - ->set_content( $this->get_content() ) - ->set_content_map( $this->get_content_map ); - - $summary = get_post_meta( $this->wp_post->ID, 'event-summary', true ); - if ( $summary ) { - $object->set_summary( $summary ); - } else { - $object->set_summary( $this->get_content() ); - } - - $start_time = get_post_meta( $this->wp_post->ID, 'event-start-date', true ); - $object->set_start_time( \gmdate( 'Y-m-d\TH:i:s\Z', $start_time ) ); - - $hide_end_time = get_post_meta( $this->wp_post->ID, 'event-hide-end-time', true ); - - if ( $hide_end_time != 'yes' ) { - $object->set_end_time( $this->get_end_time() ); - } - - $path = sprintf( 'users/%d/followers', intval( $this->wp_post->post_author ) ); - - $object - ->set_location( $this->get_event_location( $this->wp_post->ID )->to_array() ) - ->set_comments_enabled( comments_open( $this->wp_post->ID ) ) - ->set_to( - array( - 'https://www.w3.org/ns/activitystreams#Public', - get_rest_url_by_path( $path ), - ) - ) - ->set_cc( array( get_rest_url_by_path( $path ) ) ) - ->set_attachment( $this->get_attachments() ) - ->set_tag( $this->get_tags() ) + return $object ->set_replies_moderation_option( 'allow_all' ) ->set_join_mode( 'external' ) ->set_external_participation_url( $this->get_url() ) ->set_status( 'CONFIRMED' ) ->set_category( 'MEETING' ) - ->set_contacts( array() ) - ->set_name( get_the_title( $this->wp_post->ID ) ) + ->set_name( get_the_title( $this->object->ID ) ) ->set_timezone( 'Europe/Vienna' ) ->set_is_online( false ) ->set_in_language( 'de ' ) - ->set_actor( $this->get_attributed_to() ); - - $object->set_remaining_attendee_capacity( null ) - ->set_anonymous_participation_enabled( null ) - ->set_draft( false ); - $object->set_participant_count( 2 ); - $object->set_uuid( '1de96701-bceb-4a78-bc18-6c417f52b314' ); - - return $object; + ->set_actor ('http://wp.lan/@blog') + ->set_to ( [ + "https://www.w3.org/ns/activitystreams#Public" + ]); } }