wordpress-activitypub/includes/activity/extended-object/class-event.php
André Menrath 174262d22c
Add/event objects (#629)
* remove redundant property definitions

* Add redused context for actors.

* Add classes to construct Moblizon compatible events

* Bind the context to the activitypub object
- change the propertyname  which stores the json-ld context from context to _context, because context is already reserved in the ActivityStreams vocabulary.
- cleanup currently unused code

* fix phpcs

* Remove PostalAddress object: it's enough (at least atm) to directly write the array in transformers.

* Remove _context property from ActivityPub objects in favour of getter function get_json_ld_context()

* fix unit tests: ActivityPub Activity objects have a custom getter for the JsonLD context

* fix phpcs

* fix unit-tests to also support php5.6

* fix phpcs

* add param include_json_ld_context to to_array function
This allows to not set the @context in the resulting array.

* propagate the param include_json_ld_context to nested calls of to_array.

* fix phpcs

* Nested AcitivityPub objects: never build context in inner items in to_array function

* fix: param of set_address may also be an array

* fix typo in comment

* always prefix json-ld context with json-ld and move event class to sub-namespace

* fix usage of reserved object keyword
seems it should not be used as a namespace either

* Merge commit 'b2271cda6b857f879e0abd4f3c6683642d725267' into add/event-objects

* Fix calling non-static function as static

Co-authored-by: Matthias Pfefferle <pfefferle@users.noreply.github.com>

* Partly fix Json-LD contexts in collections

* Update includes/activity/class-base-object.php

* this is implicit

We already set the correct user with `$transformer->change_wp_user_id( $user_id );` so the Actor will be generated properly. We can change the behaviour, but we should not use both.

* this change prevents the Activity to re-use Object vars

this should stay as is, because it pre-fills the Activity with data (for example cc and to) and it will no longer be done with your change.

It is on purpose that it first sets the object and then replaces it with the URI.

See: https://github.com/Automattic/wordpress-activitypub/blob/master/includes/activity/class-activity.php#L195

* add `$include_json_ld_context` support to `to_json`

* disable some more contexts

* remove whitespace

* Add php-comment for 7ed17c042a

* Fix JSON-LD context for ActivityPub objects: child classes may override it.

* coding standards

* call folder/namespace `Extended_Object`

 to be consistent with folder names in singular

* fix: unnessesary nesting of extended-objects

* remove license

I hope this is fine, to have the complete plugin under the MIT @Menrath ?!?

---------

Co-authored-by: Matthias Pfefferle <pfefferle@users.noreply.github.com>
2024-01-18 16:35:52 +01:00

340 lines
8.5 KiB
PHP

<?php
/**
* ActivityPub Object of type Event.
*
* @package activity-event-transformers
*/
namespace Activitypub\Activity\Extended_Object;
use Activitypub\Activity\Base_Object;
/**
* 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 {
// Human friendly minimal context for full Mobilizon compatible ActivityPub events.
const JSON_LD_CONTEXT = array(
'https://schema.org/', // The base context is schema.org, cause it is used a lot.
'https://www.w3.org/ns/activitystreams', // The ActivityStreams context overrides everyting also defined in schema.org.
array( // The keys here override/extend the context even more.
'pt' => 'https://joinpeertube.org/ns#',
'mz' => 'https://joinmobilizon.org/ns#',
'status' => 'http://www.w3.org/2002/12/cal/ical#status',
'commentsEnabled' => 'pt:commentsEnabled',
'isOnline' => 'mz:isOnline',
'timezone' => 'mz:timezone',
'participantCount' => 'mz:participantCount',
'anonymousParticipationEnabled' => 'mz:anonymousParticipationEnabled',
'joinMode' => array(
'@id' => 'mz:joinMode',
'@type' => 'mz:joinModeType',
),
'externalParticipationUrl' => array(
'@id' => 'mz:externalParticipationUrl',
'@type' => 'schema:URL',
),
'repliesModerationOption' => array(
'@id' => 'mz:repliesModerationOption',
'@type' => '@vocab',
),
'contacts' => array(
'@id' => 'mz:contacts',
'@type' => '@id',
),
),
);
/**
* Mobilizon compatible values for repliesModertaionOption.
* @var array
*/
const REPLIES_MODERATION_OPTION_TYPES = array( 'allow_all', 'closed' );
/**
* Mobilizon compatible values for joinModeTypes.
*/
const JOIN_MODE_TYPES = array( 'free', 'restricted', 'external' ); // and 'invite', but not used by mobilizon atm
/**
* Allowed values for ical VEVENT STATUS.
* @var array
*/
const ICAL_EVENT_STATUS_TYPES = array( 'TENTATIVE', 'CONFIRMED', 'CANCELLED' );
/**
* Default event categories.
*
* These values currently reflect the default set as proposed by Mobilizon to maximize interoperability.
* @var array
*/
const DEFAULT_EVENT_CATEGORIES = array(
'ARTS',
'BOOK_CLUBS',
'BUSINESS',
'CAUSES',
'COMEDY',
'CRAFTS',
'FOOD_DRINK',
'HEALTH',
'MUSIC',
'AUTO_BOAT_AIR',
'COMMUNITY',
'FAMILY_EDUCATION',
'FASHION_BEAUTY',
'FILM_MEDIA',
'GAMES',
'LANGUAGE_CULTURE',
'LEARNING',
'LGBTQ',
'MOVEMENTS_POLITICS',
'NETWORKING',
'PARTY',
'PERFORMING_VISUAL_ARTS',
'PETS',
'PHOTOGRAPHY',
'OUTDOORS_ADVENTURE',
'SPIRITUALITY_RELIGION_BELIEFS',
'SCIENCE_TECH',
'SPORTS',
'THEATRE',
'MEETING', // Default value.
);
/**
* Event is an implementation of one of the
* Activity Streams
*
* @var string
*/
protected $type = 'Event';
/**
* The Title of the event.
*/
protected $name;
/**
* The events contacts
*
* @context {
* '@id' => 'mz:contacts',
* '@type' => '@id',
* }
*
* @var array Array of contacts (ActivityPub actor IDs).
*/
protected $contacts;
/**
* 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|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;
/**
* Which actor created the event.
*
* This field is needed due to the current group structure of Mobilizon.
*
* @todo this seems to not be a default property of an Object but needed by mobilizon.
* @var string
*/
protected $actor;
/**
* @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;
/**
* Setter for the timezone.
*
* The passed timezone is only set when it is a valid one, otherwise the site's timezone is used.
*
* @param string $timezone The timezone string to be set, e.g. 'Europe/Berlin'.
*/
public function set_timezone( $timezone ) {
if ( in_array( $timezone, timezone_identifiers_list(), true ) ) {
$this->timezone = $timezone;
} else {
$this->timezone = wp_timezone_string();
}
return $this;
}
/**
* Custom setter for repliesModerationOption which also directy sets commentsEnabled accordingly.
*
* @param string $type
*/
public function set_replies_moderation_option( $type ) {
if ( in_array( $type, self::REPLIES_MODERATION_OPTION_TYPES, true ) ) {
$this->replies_moderation_option = $type;
$this->comments_enabled = ( 'allow_all' === $type ) ? true : false;
} else {
_doing_it_wrong(
__METHOD__,
'The replies moderation option must be either allow_all or closed.',
'<version_placeholder>'
);
}
return $this;
}
/**
* Custom setter for commentsEnabled which also directly sets repliesModerationOption accordingly.
*
* @param bool $comments_enabled
*/
public function set_comments_enabled( $comments_enabled ) {
if ( is_bool( $comments_enabled ) ) {
$this->comments_enabled = $comments_enabled;
$this->replies_moderation_option = $comments_enabled ? 'allow_all' : 'closed';
} else {
_doing_it_wrong(
__METHOD__,
'The commentsEnabled must be boolean.',
'<version_placeholder>'
);
}
return $this;
}
/**
* Custom setter for the ical status that checks whether the status is an ical event status.
*
* @param string $status
*/
public function set_status( $status ) {
if ( in_array( $status, self::ICAL_EVENT_STATUS_TYPES, true ) ) {
$this->status = $status;
} else {
_doing_it_wrong(
__METHOD__,
'The status of the event must be a VEVENT iCal status.',
'<version_placeholder>'
);
}
return $this;
}
/**
* Custom setter for the event category.
*
* Falls back to Mobilizons default category.
*
* @param string $category
* @param bool $mobilizon_compatibilty Whether the category must be compatibly with Mobilizon.
*/
public function set_category( $category, $mobilizon_compatibilty = true ) {
if ( $mobilizon_compatibilty ) {
$this->category = in_array( $category, self::DEFAULT_EVENT_CATEGORIES, true ) ? $category : 'MEETING';
} else {
$this->category = $category;
}
return $this;
}
/**
* Custom setter for an external participation url.
*
* Automatically sets the joinMode to true if called.
*
* @param string $url
*/
public function set_external_participation_url( $url ) {
if ( preg_match( '/^https?:\/\/.*/i', $url ) ) {
$this->external_participation_url = $url;
$this->join_mode = 'external';
}
return $this;
}
}