Skip to content

Commit

Permalink
Add/event objects (#629)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* 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 7ed17c0

* 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 <[email protected]>
  • Loading branch information
Menrath and pfefferle authored Jan 18, 2024
1 parent b612ce0 commit 174262d
Show file tree
Hide file tree
Showing 24 changed files with 585 additions and 148 deletions.
2 changes: 1 addition & 1 deletion activitypub.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ function ( $full_class ) {
if ( false !== strpos( $class, '\\' ) ) {
$parts = explode( '\\', $class );
$class = array_pop( $parts );
$sub_dir = implode( '/', $parts );
$sub_dir = strtr( implode( '/', $parts ), '_', '-' );
$base_dir = $base_dir . $sub_dir . '/';
}

Expand Down
78 changes: 16 additions & 62 deletions includes/activity/class-activity.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,75 +17,15 @@
* @see https://www.w3.org/TR/activitystreams-core/#intransitiveactivities
*/
class Activity extends Base_Object {
const CONTEXT = array(
const JSON_LD_CONTEXT = array(
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1',
'https://purl.archive.org/socialweb/webfinger',
array(
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
'PropertyValue' => 'schema:PropertyValue',
'schema' => 'http://schema.org#',
'pt' => 'https://joinpeertube.org/ns#',
'toot' => 'http://joinmastodon.org/ns#',
'litepub' => 'http://litepub.social/ns#',
'lemmy' => 'https://join-lemmy.org/ns#',
'value' => 'schema:value',
'Hashtag' => 'as:Hashtag',
'featured' => array(
'@id' => 'toot:featured',
'@type' => '@id',
),
'featuredTags' => array(
'@id' => 'toot:featuredTags',
'@type' => '@id',
),
'alsoKnownAs' => array(
'@id' => 'as:alsoKnownAs',
'@type' => '@id',
),
'moderators' => array(
'@id' => 'lemmy:moderators',
'@type' => '@id',
),
'postingRestrictedToMods' => 'lemmy:postingRestrictedToMods',
'discoverable' => 'toot:discoverable',
'indexable' => 'toot:indexable',
'sensitive' => 'as:sensitive',
),
);

/**
* The object's unique global identifier
*
* @see https://www.w3.org/TR/activitypub/#obj-id
*
* @var string
*/
protected $id;

/**
* @var string
*/
protected $type = 'Activity';

/**
* The context within which the object exists or an activity was
* performed.
* The notion of "context" used is intentionally vague.
* The intended function is to serve as a means of grouping objects
* and activities that share a common originating context or
* purpose. An example could be all activities relating to a common
* project or event.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context
*
* @var string
* | ObjectType
* | Link
* | null
*/
protected $context = self::CONTEXT;

/**
* Describes the direct object of the activity.
* For instance, in the activity "John added a movie to his
Expand All @@ -94,7 +34,7 @@ class Activity extends Base_Object {
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object-term
*
* @var string
* | Base_Objectr
* | Base_Object
* | Link
* | null
*/
Expand Down Expand Up @@ -225,4 +165,18 @@ public function set_object( $object ) {
$this->set( 'id', $object->get_id() . '#activity' );
}
}

/**
* 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 ( $this->object instanceof Base_Object ) {
// Without php 5.6 support this could be just: 'return $this->object::JSON_LD_CONTEXT;'
return call_user_func( array( get_class( $this->object ), 'CONTEXT' ) );
} else {
return self::JSON_LD_CONTEXT;
}
}
}
35 changes: 35 additions & 0 deletions includes/activity/class-actor.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,39 @@
* @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types
*/
class Actor extends Base_Object {
// Reduced context for actors. TODO: still unused.
const JSON_LD_CONTEXT = array(
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1',
'https://purl.archive.org/socialweb/webfinger',
array(
'schema' => 'http://schema.org#',
'toot' => 'http://joinmastodon.org/ns#',
'webfinger' => 'https://webfinger.net/#',
'lemmy' => 'https://join-lemmy.org/ns#',
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
'PropertyValue' => 'schema:PropertyValue',
'value' => 'schema:value',
'Hashtag' => 'as:Hashtag',
'featured' => array(
'@id' => 'toot:featured',
'@type' => '@id',
),
'featuredTags' => array(
'@id' => 'toot:featuredTags',
'@type' => '@id',
),
'moderators' => array(
'@id' => 'lemmy:moderators',
'@type' => '@id',
),
'postingRestrictedToMods' => 'lemmy:postingRestrictedToMods',
'discoverable' => 'toot:discoverable',
'indexable' => 'toot:indexable',
'resource' => 'webfinger:resource',
),
);

/**
* @var string
*/
Expand Down Expand Up @@ -133,6 +166,8 @@ class Actor extends Base_Object {
*
* @see https://docs.joinmastodon.org/spec/activitypub/#as
*
* @context as:manuallyApprovesFollowers
*
* @var boolean
*/
protected $manually_approves_followers = false;
Expand Down
41 changes: 30 additions & 11 deletions includes/activity/class-base-object.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use WP_Error;
use ReflectionClass;
use DateTime;

use function Activitypub\camel_to_snake_case;
use function Activitypub\snake_to_camel_case;
Expand All @@ -26,6 +27,13 @@
* @see https://www.w3.org/TR/activitystreams-core/#object
*/
class Base_Object {
const JSON_LD_CONTEXT = array(
'https://www.w3.org/ns/activitystreams',
array(
'Hashtag' => 'as:Hashtag',
),
);

/**
* The object's unique global identifier
*
Expand Down Expand Up @@ -457,7 +465,7 @@ public function __call( $method, $params ) {
}

if ( \strncasecmp( $method, 'set', 3 ) === 0 ) {
$this->set( $var, $params[0] );
return $this->set( $var, $params[0] );
}

if ( \strncasecmp( $method, 'add', 3 ) === 0 ) {
Expand Down Expand Up @@ -524,7 +532,7 @@ public function set( $key, $value ) {

$this->$key = $value;

return $this->$key;
return $this;
}

/**
Expand Down Expand Up @@ -622,9 +630,11 @@ public function from_array( $array ) {
* It tries to get the object attributes if they exist
* and falls back to the getters. Empty values are ignored.
*
* @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true.
*
* @return array An array built from the Object.
*/
public function to_array() {
public function to_array( $include_json_ld_context = true ) {
$array = array();
$vars = get_object_vars( $this );

Expand All @@ -640,7 +650,7 @@ public function to_array() {
}

if ( is_object( $value ) ) {
$value = $value->to_array();
$value = $value->to_array( false );
}

// if value is still empty, ignore it for the array and continue.
Expand All @@ -649,11 +659,9 @@ public function to_array() {
}
}

// replace 'context' key with '@context' and move it to the top.
if ( array_key_exists( 'context', $array ) ) {
$context = $array['context'];
unset( $array['context'] );
$array = array_merge( array( '@context' => $context ), $array );
if ( $include_json_ld_context ) {
// Get JsonLD context and move it to '@context' at the top.
$array = array_merge( array( '@context' => $this->get_json_ld_context() ), $array );
}

$class = new ReflectionClass( $this );
Expand All @@ -668,10 +676,12 @@ public function to_array() {
/**
* Convert Object to JSON.
*
* @param bool $include_json_ld_context Whether to include the JSON-LD context. Default true.
*
* @return string The JSON string.
*/
public function to_json() {
$array = $this->to_array();
public function to_json( $include_json_ld_context = true ) {
$array = $this->to_array( $include_json_ld_context );
$options = \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_QUOT;

/*
Expand All @@ -692,4 +702,13 @@ public function to_json() {
public function get_object_var_keys() {
return \array_keys( \get_object_vars( $this ) );
}

/**
* Returns the JSON-LD context of this object.
*
* @return array $context A compacted JSON-LD context for the ActivityPub object.
*/
public function get_json_ld_context() {
return static::JSON_LD_CONTEXT;
}
}
3 changes: 3 additions & 0 deletions includes/activity/extended-object/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
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.
Loading

0 comments on commit 174262d

Please sign in to comment.