Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add/extendable transformers #569

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
38be586
initial draft: add/extendable-transformers
Menrath Nov 20, 2023
3ae71bb
fix the wrongs calld of the get_transformer
Menrath Nov 20, 2023
6d40ebf
Automatically set the wp_post when returning a transformer instance f…
Menrath Nov 20, 2023
0ccb6c9
fix: add missing self prefix of class constant
Menrath Nov 20, 2023
246600b
add: untestet draft of the migration for the activated post type setting
Menrath Nov 20, 2023
2113d3e
update phpdocs
Menrath Nov 20, 2023
0501fc5
Merge remote-tracking branch 'origin/master' into add/extendable-tran…
Menrath Nov 21, 2023
3a5b530
Merge branch 'master' into add/extendable-transformers
pfefferle Nov 21, 2023
369b32b
transformer: move all related code to \Activitypub\Transformer namespace
Menrath Nov 22, 2023
c857eee
transformer: move all related code to \Activitypub\Transformer namespace
Menrath Nov 22, 2023
0bd6ecc
typo
Menrath Nov 22, 2023
804cb0a
fix phpcs errors
Menrath Nov 22, 2023
ed1b6b7
change hook name for registering transformers
Menrath Nov 22, 2023
75f1da1
Merge branch 'master' into add/extendable-transformers
pfefferle Nov 24, 2023
2a79297
Merge branch 'add/extendable-transformers' of ssh://code.event-federa…
Menrath Nov 25, 2023
81f971b
fix creation of new transformer instance
Menrath Nov 25, 2023
8338ea4
fix: make in_array comparison strict
Menrath Nov 25, 2023
47b7d84
cleanup: remove function get_post_content_template that is now presen…
Menrath Nov 25, 2023
d25a5c2
fix: forgotten merge conflict
Menrath Nov 25, 2023
82928fb
fix phpdocs
Menrath Nov 25, 2023
9c20c8f
fix init of new transformer instance
Menrath Nov 25, 2023
768d190
move transofmrer function get_post_content_template to base class
Menrath Nov 25, 2023
e5d19f2
fix phpdocs and some readability
Menrath Nov 25, 2023
c7ff99e
fix phpcs via phpcbf
Menrath Nov 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions activitypub.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@
\defined( 'ACTIVITYPUB_CUSTOM_POST_CONTENT' ) || \define( 'ACTIVITYPUB_CUSTOM_POST_CONTENT', "<strong>[ap_title]</strong>\n\n[ap_content]\n\n[ap_hashtags]\n\n[ap_shortlink]" );
\defined( 'ACTIVITYPUB_AUTHORIZED_FETCH' ) || \define( 'ACTIVITYPUB_AUTHORIZED_FETCH', false );
\defined( 'ACTIVITYPUB_DISABLE_REWRITES' ) || \define( 'ACTIVITYPUB_DISABLE_REWRITES', false );
\defined( 'ACTIVITYPUB_DEFAULT_TRANSFORMER' ) || \define( 'ACTIVITYPUB_DEFAULT_TRANSFORMER', 'activitypub/default' );


\define( 'ACTIVITYPUB_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
\define( 'ACTIVITYPUB_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
\define( 'ACTIVITYPUB_PLUGIN_FILE', plugin_dir_path( __FILE__ ) . '/' . basename( __FILE__ ) );
\define( 'ACTIVITYPUB_PLUGIN_URL', plugin_dir_url( __FILE__ ) );


/**
* Initialize REST routes.
*/
Expand Down
23 changes: 23 additions & 0 deletions includes/activity/class-event.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why these classes? I tried to avoid them, because otherwise we also have to map all other types https://github.com/Automattic/wordpress-activitypub/blob/master/includes/transformer/class-post.php#L398

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are still evaluating all pros and cons. At the moment we have only tried to get an idea of what the consequences would be. As is often the case: the deeper I dig into this repository, the more I can understand certain design decisions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but there are things that are simply legacy decisions! Be aware that this project started as a spare time thing and still has some crappy code everywhere. So do not try to understand everything and feel free to challenge us, that's what I also try here ;)

I discuss to understand, not to win :)

Copy link
Contributor Author

@Menrath Menrath Nov 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, for offering help, even at our Drafting Stage. I gladly accept this invitation for discussions :)

One of my goals is, that it is very easy an straight forward, for feature developers adding their own transformers to their plugins. Very likely they will have to extend the Base_Object class anyway, especially if they want to add any custom fields that are not defined yet in our Base_Objet class, which until now is consistent with the Activitystreams Vocabulary Standard, e.g., Mobilizon makes usage of PeerTubes commentsEnabled feature within its Event object which is a object type available in the ActivityPub standard.

Other developers might have a look how thinks are done in this project, and might get confused if the activitypub plugin itself does things a bit differently than the future documentation for how to add proper activitiypub support for my custom post type might advice them to do.

Another related issue is, that when adding a custom field, one also has to add the appropriate json-ld context.
Though the filter activitypub_json_context is available, editing the array directly seemed kind of rough to me and applying the filter within the transformer code leaded to a runtime issue, so I had to apply this filter in a different part of the code, which is not ideal in my opinion: doing one "thing" on two different places.

I will share our repository with some example transformers registering to the ActivityPub-plugin hopefully today, after doing some renaming and initial documentation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will share our repository with some example transformers registering to the ActivityPub-plugin hopefully today, after doing some renaming and initial documentation.

That would be perfect!

I agree with your point, but I am not sure if the "extensions" (Event-Activity) should be part of this repo or part of yours. I agree, that it has to be as easy as possible and maybe we have to change the current context implementation for that.

You can maybe have a look what I did to extend the base object(s) for the Follower (https://github.com/Automattic/wordpress-activitypub/blob/master/includes/model/class-follower.php) or internal User mapping (https://github.com/Automattic/wordpress-activitypub/blob/master/includes/model/class-user.php).

/**
* Inspired by the PHP ActivityPub Library by @Landrok
*
* @link https://github.com/landrok/activitypub
*/

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 Note extends Base_Object {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class Note extends Base_Object {
class Event extends Base_Object {

protected $type = 'Event';
}
23 changes: 23 additions & 0 deletions includes/activity/class-note.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
/**
* Inspired by the PHP ActivityPub Library by @Landrok
*
* @link https://github.com/landrok/activitypub
*/

namespace Activitypub\Activity;

use Activitypub\Activity\Base_Object;

/**
* Note is an implementation of one of the
* Activity Streams Note object type
*
* The Object is the primary base type for the Activity Streams
* vocabulary.
*
* @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note
*/
class Note extends Base_Object {
protected $type = 'Note';
}
8 changes: 5 additions & 3 deletions includes/class-activity-dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Activitypub\Activity\Activity;
use Activitypub\Collection\Users;
use Activitypub\Collection\Followers;
use Activitypub\Transformer\Post;
use Activitypub\Transformer\Transformers_Manager;

use function Activitypub\is_single_user;
use function Activitypub\is_user_disabled;
Expand Down Expand Up @@ -65,7 +65,8 @@ public static function send_activity( WP_Post $wp_post, $type ) {
return;
}

$object = Post::transform( $wp_post )->to_object();
$transformer = Transformers_Manager::instance()->get_transformer( $wp_post );
$object = $transformer->to_object();

$activity = new Activity();
$activity->set_type( $type );
Expand Down Expand Up @@ -101,7 +102,8 @@ public static function send_announce( WP_Post $wp_post, $type ) {
return;
}

$object = Post::transform( $wp_post )->to_object();
$transformer = Transformers_Manager::instance()->get_transformer( $wp_post );
$object = $transformer->to_object();

$activity = new Activity();
$activity->set_type( 'Announce' );
Expand Down
4 changes: 2 additions & 2 deletions includes/class-activitypub.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public static function init() {
\add_filter( 'get_comment_link', array( self::class, 'remote_comment_link' ), 11, 3 );

// Add support for ActivityPub to custom post types
$post_types = \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) ? \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) ) : array();
$transformer_mapping = \get_option( 'activitypub_transformer_mapping', array( 'post' => 'activitypub/default', 'page' => 'activitypub/default' ) ) ? \get_option( 'activitypub_transformer_mapping', array( 'post' => 'activitypub/default', 'page' => 'activitypub/default' ) ) : array();

foreach ( $post_types as $post_type ) {
foreach ( array_keys( $transformer_mapping ) as $post_type ) {
\add_post_type_support( $post_type, 'activitypub' );
}

Expand Down
55 changes: 49 additions & 6 deletions includes/class-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use WP_User_Query;
use Activitypub\Model\Blog_User;
use Activitypub\Base\Transformer\Base as Transformer_Base;

/**
* ActivityPub Admin Class
Expand All @@ -22,6 +23,15 @@ public static function init() {
if ( ! is_user_disabled( get_current_user_id() ) ) {
\add_action( 'show_user_profile', array( self::class, 'add_profile' ) );
}

add_filter(
'activitypub/transformers/is_transformer_enabled',
function( $should_register, Transformer_Base $transformer_instance ) {
return ! Options::is_transformer_disabled( $transformer_instance->get_name() );
},
10,
2
);
}

/**
Expand Down Expand Up @@ -154,14 +164,47 @@ public static function register_settings() {
'default' => '0',
)
);
\register_setting(

/**
* Flexible activation of post_types together with mapping ActivityPub transformers.
*
* If a post-type is not mapped to any ActivtiyPub transformer it means it is not activated
* for ActivityPub federation.
*
* @since version_number_transformer_management_placeholder
*/
register_setting(
'activitypub',
'activitypub_support_post_types',
'activitypub_transformer_mapping',
array(
'type' => 'string',
'description' => \esc_html__( 'Enable ActivityPub support for post types', 'activitypub' ),
'show_in_rest' => true,
'default' => array( 'post', 'pages' ),
'type' => 'array',
'default' => array(
'post' => 'note',
),
'show_in_rest' => array(
'schema' => array(
'type' => 'array',
'items' => array(
'type' => 'string',
),
),
),
'sanitize_callback' => function ( $value ) {
// Check if $value is an array
if ( ! is_array( $value ) ) {
return array();
}
$value_keys = array_keys( $value );

$all_public_post_types = \get_post_types( array( 'public' => true ), 'names' );

// Unset the keys that are missing in $keysToCheck
foreach ( array_diff( $value_keys, $all_public_post_types ) as $missing_key ) {
unset( $value[ $missing_key ] );
}
// var_dump($value);
return $value;
},
)
);
\register_setting(
Expand Down
19 changes: 19 additions & 0 deletions includes/class-migration.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use Activitypub\Activitypub;
use Activitypub\Model\Blog_User;
use Activitypub\Collection\Followers;
use Activitypub\Admin;

/**
* ActivityPub Migration Class
Expand Down Expand Up @@ -114,12 +115,30 @@ public static function maybe_migrate() {
if ( version_compare( $version_from_db, '1.0.0', '<' ) ) {
self::migrate_from_0_17();
}
if ( version_compare( $version_from_db, 'version_number_transformer_management_placeholder', '<' ) ) {
self::migrate_from_version_number_transformer_management_placeholder();
}

update_option( 'activitypub_db_version', self::get_target_version() );

self::unlock();
}

/**
* 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_DEFAULT_TRANSFORMER;
}
update_option( 'activitypub_transformer_mapping', $transformer_mapping );
}

/**
* Updates the DB-schema of the followers-list
*
Expand Down
1 change: 0 additions & 1 deletion includes/class-scheduler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Activitypub\Collection\Users;
use Activitypub\Collection\Followers;
use Activitypub\Transformer\Post;

/**
* ActivityPub Scheduler Class
Expand Down
7 changes: 4 additions & 3 deletions includes/model/class-post.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
namespace Activitypub\Model;

use Activitypub\Transformer\Post as Post_Transformer;
use Activitypub\Transformer\Post as Transformer_Post;

/**
* ActivityPub Post Class
Expand Down Expand Up @@ -33,8 +33,9 @@ class Post {
public function __construct( $post, $post_author = null ) {
_deprecated_function( __CLASS__, '1.0.0', '\Activitypub\Transformer\Post' );

$this->post = $post;
$this->object = Post_Transformer::transform( $post )->to_object();
$this->post = $post;
$transformer = new Transformer_Post();
$this->object = $transformer->set_wp_post( $post )->to_object();
}

/**
Expand Down
4 changes: 2 additions & 2 deletions includes/rest/class-collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use WP_Error;
use WP_REST_Server;
use WP_REST_Response;
use Activitypub\Transformer\Post;
use Activitypub\Transformer\Transformers_Manager;
use Activitypub\Activity\Activity;
use Activitypub\Collection\Users as User_Collection;

Expand Down Expand Up @@ -168,7 +168,7 @@ public static function featured_get( $request ) {
);

foreach ( $posts as $post ) {
$response['orderedItems'][] = Post::transform( $post )->to_object()->to_array();
$response['orderedItems'][] = Transformers_Manager::instance()->get_transformer( $post )->to_object()->to_array();
}

$rest_response = new WP_REST_Response( $response, 200 );
Expand Down
7 changes: 4 additions & 3 deletions includes/rest/class-outbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use WP_Error;
use WP_REST_Server;
use WP_REST_Response;
use Activitypub\Transformer\Post;
use Activitypub\Transformer\Transformers_Manager;
use Activitypub\Activity\Activity;
use Activitypub\Collection\Users as User_Collection;

Expand Down Expand Up @@ -59,7 +59,7 @@ public static function user_outbox_get( $request ) {
return $user;
}

$post_types = \get_option( 'activitypub_support_post_types', array( 'post', 'page' ) );
$post_types = array_keys( \get_option( 'activitypub_transformer_mapping', array( 'post' => 'activitypub/default', 'page' => 'activitypub/default' ) ) );

$page = $request->get_param( 'page', 1 );

Expand Down Expand Up @@ -105,7 +105,8 @@ public static function user_outbox_get( $request ) {
);

foreach ( $posts as $post ) {
$post = Post::transform( $post )->to_object();
$transformer = \Activitypub\Transformer\Transformers_Manager::instance()->get_transformer( $post );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$transformer = \Activitypub\Transformer\Transformers_Manager::instance()->get_transformer( $post );
$transformer = Transformers_Manager::instance()->get_transformer( $post );

you do not have to use the full path (with namespaces) when using use.

$post = $transformer->to_object();
$activity = new Activity();
$activity->set_type( 'Create' );
$activity->set_context( null );
Expand Down