Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
1e29453
Refactor notification system to use action hooks
pfefferle Sep 22, 2025
8488156
Update includes/handler/class-update.php
pfefferle Sep 22, 2025
ce5869e
Update includes/handler/class-accept.php
pfefferle Sep 22, 2025
f902344
Update integration/class-stream-connector.php
pfefferle Sep 22, 2025
6b10aa2
Refactor Accept handler to set $success before action
pfefferle Sep 22, 2025
c727a40
Align docblock param indentation in Stream_Connector
pfefferle Sep 22, 2025
60592c6
Add changelog
matticbot Sep 22, 2025
d4b35f9
Merge branch 'trunk' into change/deprecate-notifications
pfefferle Sep 22, 2025
8cdb9c9
Merge branch 'trunk' into change/deprecate-notifications
pfefferle Sep 22, 2025
52d2e12
Update Accept handler action parameters
pfefferle Sep 23, 2025
78714cf
Rename $reaction variable to $result in Announce handler
pfefferle Sep 23, 2025
5ad1d1b
Rename variable from reaction to result in Create handler
pfefferle Sep 23, 2025
7dbefe0
Update maybe_delete_follower return value and doc
pfefferle Sep 23, 2025
3602a89
Standardize action hook parameter types and names
pfefferle Sep 23, 2025
d7baeac
Fix duplicate parameter in do_action call
pfefferle Sep 23, 2025
d8671c5
Change move status default from null to false
pfefferle Sep 23, 2025
ca158dc
Add deprecation notices to ActivityPub actions
pfefferle Sep 23, 2025
c5ea0f3
Update includes/handler/class-accept.php
pfefferle Sep 23, 2025
ba09426
Update includes/handler/class-announce.php
pfefferle Sep 23, 2025
f9b7ec0
Update includes/handler/class-create.php
pfefferle Sep 23, 2025
0e59f0c
Update includes/handler/class-reject.php
pfefferle Sep 23, 2025
a881a53
Update includes/handler/class-undo.php
pfefferle Sep 23, 2025
4ce56c4
Update includes/handler/class-delete.php
pfefferle Sep 23, 2025
d17a84f
Update includes/handler/class-update.php
pfefferle Sep 23, 2025
653e703
Update includes/handler/class-delete.php
pfefferle Sep 23, 2025
41d7d33
Update includes/handler/class-follow.php
pfefferle Sep 23, 2025
6fb1953
Update includes/handler/class-update.php
pfefferle Sep 23, 2025
b6b0548
Update includes/handler/class-inbox.php
pfefferle Sep 23, 2025
7863f65
Update includes/handler/class-like.php
pfefferle Sep 23, 2025
4581f07
Refactor handler actions to use success flag and result
pfefferle Sep 24, 2025
2ed1715
Fix docblock formatting in Accept handler
pfefferle Sep 24, 2025
18db869
Clarify $success param in handler docblocks
pfefferle Sep 24, 2025
6622b09
Improve parameter docs and variable naming consistency
pfefferle Sep 24, 2025
b75a119
Refactor Undo handler and add object validation
pfefferle Sep 24, 2025
df7b974
Allow remove() to accept WP_Post or ID in Followers
pfefferle Sep 24, 2025
18be575
Add unit tests for Undo handler functionality
pfefferle Sep 24, 2025
0fd91bf
Refactor undo handler tests to use data providers
pfefferle Sep 24, 2025
8624bdc
Expand and refactor follow handler tests
pfefferle Sep 24, 2025
71185f2
Expand Like handler tests with new scenarios and hooks
pfefferle Sep 24, 2025
0e2069d
Refactor and expand handler tests with data providers
pfefferle Sep 24, 2025
4718038
Refactor get_type tests to use data provider
pfefferle Sep 24, 2025
141d895
Refactor inbox handler test with data provider
pfefferle Sep 24, 2025
c2556bb
Remove redundant @covers annotation in inbox test
pfefferle Sep 24, 2025
35e4395
Add integration tests for Stream Connector
pfefferle Sep 24, 2025
dfd7151
Add test for prepare_outbox_data_for_response with blog user URL
pfefferle Sep 24, 2025
7742452
Merge branch 'trunk' into change/deprecate-notifications
pfefferle Sep 24, 2025
0aa68c1
Merge branch 'trunk' into change/deprecate-notifications
pfefferle Sep 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 6 additions & 13 deletions includes/class-notification.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

/**
* Notification class.
*
* @deprecated unreleased Use action hooks like 'activitypub_handled_{type}' instead.
*/
class Notification {
/**
Expand Down Expand Up @@ -48,6 +50,8 @@ class Notification {
* @param int $target The WordPress User-Id.
*/
public function __construct( $type, $actor, $activity, $target ) {
\_deprecated_class( __CLASS__, 'unreleased', 'Use action hooks like "activitypub_handled_{type}" instead.' );

$this->type = $type;
$this->actor = $actor;
$this->object = $activity;
Expand All @@ -60,18 +64,7 @@ public function __construct( $type, $actor, $activity, $target ) {
public function send() {
$type = \strtolower( $this->type );

/**
* Action to send ActivityPub notifications.
*
* @param Notification $instance The notification object.
*/
do_action( 'activitypub_notification', $this );

/**
* Type-specific action to send ActivityPub notifications.
*
* @param Notification $instance The notification object.
*/
do_action( "activitypub_notification_{$type}", $this );
\do_action_deprecated( 'activitypub_notification', array( $this ), 'unreleased', "activitypub_handled_{$type}" );
\do_action_deprecated( "activitypub_notification_{$type}", array( $this ), 'unreleased', "activitypub_handled_{$type}" );
}
}
37 changes: 13 additions & 24 deletions includes/handler/class-accept.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Activitypub\Collection\Following;
use Activitypub\Collection\Outbox;
use Activitypub\Collection\Remote_Actors;
use Activitypub\Notification;

use function Activitypub\object_to_uri;

Expand All @@ -22,19 +21,8 @@ class Accept {
* Initialize the class, registering WordPress hooks.
*/
public static function init() {
\add_action(
'activitypub_inbox_accept',
array( self::class, 'handle_accept' ),
10,
2
);

\add_filter(
'activitypub_validate_object',
array( self::class, 'validate_object' ),
10,
3
);
\add_action( 'activitypub_inbox_accept', array( self::class, 'handle_accept' ), 10, 2 );
\add_filter( 'activitypub_validate_object', array( self::class, 'validate_object' ), 10, 3 );
}

/**
Expand All @@ -60,16 +48,17 @@ public static function handle_accept( $accept, $user_id ) {
return;
}

Following::accept( $actor_post, $user_id );

// Send notification.
$notification = new Notification(
'accept',
$actor_post->guid,
$accept,
$user_id
);
$notification->send();
$reaction = Following::accept( $actor_post, $user_id );

/**
* Fires after an ActivityPub Accept activity has been handled.
*
* @param array $accept The ActivityPub activity data.
* @param int|null $user_id The local user ID, or null if not applicable.
* @param mixed $reaction The result of accepting the follow request.
* @param mixed|null $reaction The result of accepting the follow request (duplicate parameter).
*/
\do_action( 'activitypub_handled_accept', $accept, $user_id, $reaction, $reaction );
}

/**
Expand Down
19 changes: 7 additions & 12 deletions includes/handler/class-announce.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,7 @@ class Announce {
* Initialize the class, registering WordPress hooks.
*/
public static function init() {
\add_action(
'activitypub_inbox_announce',
array( self::class, 'handle_announce' ),
10,
3
);
\add_action( 'activitypub_inbox_announce', array( self::class, 'handle_announce' ), 10, 3 );
}

/**
Expand Down Expand Up @@ -114,13 +109,13 @@ public static function maybe_save_announce( $activity, $user_id ) {
}

/**
* Fires after an Announce has been saved.
* Fires after an ActivityPub Announce activity has been handled.
*
* @param array $activity The activity-object.
* @param int $user_id The id of the local blog-user.
* @param mixed $state The state of the reaction.
* @param mixed $reaction The reaction.
* @param array $activity The ActivityPub activity data.
* @param int|null $user_id The local user ID, or null if not applicable.
* @param mixed $state The state/result of the operation (e.g., comment ID, WP_Error, or status).
* @param mixed|null $reaction The WP_Comment object of the created announce/repost comment, or null if creation failed.
*/
do_action( 'activitypub_handled_announce', $activity, $user_id, $state, $reaction );
\do_action( 'activitypub_handled_announce', $activity, $user_id, $state, $reaction );
}
}
25 changes: 7 additions & 18 deletions includes/handler/class-create.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,8 @@ class Create {
* Initialize the class, registering WordPress hooks.
*/
public static function init() {
\add_action(
'activitypub_inbox_create',
array( self::class, 'handle_create' ),
10,
3
);

\add_filter(
'activitypub_validate_object',
array( self::class, 'validate_object' ),
10,
3
);
\add_action( 'activitypub_inbox_create', array( self::class, 'handle_create' ), 10, 3 );
\add_filter( 'activitypub_validate_object', array( self::class, 'validate_object' ), 10, 3 );
}

/**
Expand Down Expand Up @@ -80,12 +69,12 @@ public static function handle_create( $activity, $user_id, $activity_object = nu
}

/**
* Fires after a Create activity has been handled.
* Fires after an ActivityPub Create activity has been handled.
*
* @param array $activity The activity-object.
* @param int $user_id The id of the local blog-user.
* @param \WP_Comment|\WP_Error $state The comment object or WP_Error.
* @param \WP_Comment|\WP_Error|null $reaction The reaction object or WP_Error.
* @param array $activity The ActivityPub activity data.
* @param int|null $user_id The local user ID, or null if not applicable.
* @param mixed $state The state/result of the operation (e.g., comment ID, WP_Error, or status).
* @param mixed|null $reaction The WP_Comment object of the created comment, or null if creation failed.
*/
\do_action( 'activitypub_handled_create', $activity, $user_id, $state, $reaction );
}
Expand Down
23 changes: 19 additions & 4 deletions includes/handler/class-delete.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Delete {
* Initialize the class, registering WordPress hooks.
*/
public static function init() {
\add_action( 'activitypub_inbox_delete', array( self::class, 'handle_delete' ) );
\add_action( 'activitypub_inbox_delete', array( self::class, 'handle_delete' ), 10, 2 );
\add_filter( 'activitypub_defer_signature_verification', array( self::class, 'defer_signature_verification' ), 10, 2 );
\add_action( 'activitypub_delete_actor_interactions', array( self::class, 'delete_interactions' ) );

Expand All @@ -33,9 +33,12 @@ public static function init() {
* Handles "Delete" requests.
*
* @param array $activity The delete activity.
* @param int $user_id The local user ID.
*/
public static function handle_delete( $activity ) {
public static function handle_delete( $activity, $user_id ) {
$object_type = $activity['object']['type'] ?? '';
$state = null;
$reaction = null;

switch ( $object_type ) {
/*
Expand All @@ -48,7 +51,7 @@ public static function handle_delete( $activity ) {
case 'Organization':
case 'Service':
case 'Application':
self::maybe_delete_follower( $activity );
$state = self::maybe_delete_follower( $activity );
break;

/*
Expand Down Expand Up @@ -95,6 +98,16 @@ public static function handle_delete( $activity ) {
// Maybe handle Delete Activity for other Object Types.
break;
}

/**
* Fires after an ActivityPub Delete activity has been handled.
*
* @param array $activity The ActivityPub activity data.
* @param int|null $user_id The local user ID, or null if not applicable.
* @param mixed $state The state/result of the operation (e.g., comment ID, WP_Error, or status).
* @param mixed|null $reaction The result of the delete operation (e.g., WP_Comment object or deletion status).
*/
\do_action( 'activitypub_handled_delete', $activity, $user_id, $state, $reaction );
}

/**
Expand All @@ -107,9 +120,11 @@ public static function maybe_delete_follower( $activity ) {

// Verify that Actor is deleted.
if ( ! is_wp_error( $follower ) && Tombstone::exists( $activity['actor'] ) ) {
Remote_Actors::delete( $follower->ID );
$state = Remote_Actors::delete( $follower->ID );
self::maybe_delete_interactions( $activity );
}

return $state ?? null;
}

/**
Expand Down
42 changes: 17 additions & 25 deletions includes/handler/class-follow.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use Activitypub\Activity\Activity;
use Activitypub\Collection\Actors;
use Activitypub\Collection\Followers;
use Activitypub\Notification;

use function Activitypub\add_to_outbox;

Expand All @@ -23,7 +22,7 @@ class Follow {
*/
public static function init() {
\add_action( 'activitypub_inbox_follow', array( self::class, 'handle_follow' ), 10, 2 );
\add_action( 'activitypub_followers_post_follow', array( self::class, 'queue_accept' ), 10, 4 );
\add_action( 'activitypub_handled_follow', array( self::class, 'queue_accept' ), 10, 4 );
}

/**
Expand All @@ -44,46 +43,39 @@ public static function handle_follow( $activity, $user_id ) {
$activity['actor']
);

if ( \is_wp_error( $remote_actor ) ) {
return $remote_actor;
if ( ! \is_wp_error( $remote_actor ) ) {
$remote_actor = \get_post( $remote_actor );
}

$remote_actor = \get_post( $remote_actor );
\do_action_deprecated( 'activitypub_followers_post_follow', array( $activity['actor'], $activity, $user_id, $remote_actor ), 'unreleased', 'activitypub_handled_follow' );

/**
* Fires after a new follower has been added.
* Fires after a Follow activity has been handled.
*
* @param string $actor The URL of the actor (follower) who initiated the follow.
* @param array $activity The complete activity data of the follow request.
* @param int $user_id The ID of the WordPress user being followed.
* @param \WP_Post|\WP_Error $remote_actor The Actor object containing the new follower's data.
* @param array $activity The ActivityPub activity data.
* @param int|null $user_id The local user ID, or null if not applicable.
* @param mixed $remote_actor The WP_Post object of the remote actor/follower, or WP_Error if failed.
* @param mixed|null $remote_actor The WP_Post object of the remote actor/follower (duplicate parameter).
*/
do_action( 'activitypub_followers_post_follow', $activity['actor'], $activity, $user_id, $remote_actor );

// Send notification.
$notification = new Notification(
'follow',
$remote_actor->guid,
$activity,
$user_id
);
$notification->send();
\do_action( 'activitypub_handled_follow', $activity, $user_id, $remote_actor, $remote_actor );
}

/**
* Send Accept response.
*
* @param string $actor The Actor URL.
* @param array $activity_object The Activity object.
* @param int $user_id The ID of the WordPress User.
* @param \WP_Post|\WP_Error $remote_actor The Actor object.
* @param array $activity_object The ActivityPub activity data.
* @param int|null $user_id The local user ID, or null if not applicable.
* @param mixed $status The WP_Post object of the remote actor/follower, or WP_Error if failed.
* @param mixed|null $remote_actor The WP_Post object of the remote actor/follower (duplicate parameter).
*/
public static function queue_accept( $actor, $activity_object, $user_id, $remote_actor ) {
public static function queue_accept( $activity_object, $user_id, $status, $remote_actor ) {
if ( \is_wp_error( $remote_actor ) ) {
// Impossible to send a "Reject" because we can not get the Remote-Inbox.
return;
}

$actor = $activity_object['actor'];

// Only send minimal data.
$activity_object = array_intersect_key(
$activity_object,
Expand Down
10 changes: 5 additions & 5 deletions includes/handler/class-inbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ public static function handle_inbox_requests( $data, $user_id, $type, $activity
$id = Inbox_Collection::add( $activity, $user_id );

/**
* Fires after an inbox item has been handled.
* Fires after an ActivityPub Inbox activity has been handled.
*
* @param array $data The data array.
* @param int $user_id The ID of the local blog user.
* @param \WP_Error|int $id The ID of the inbox item.
* @param Activity|\WP_Error $activity The Activity object.
* @param array $data The ActivityPub activity data.
* @param int|null $user_id The local user ID, or null if not applicable.
* @param mixed $id The ID of the inbox item that was created, or WP_Error if failed.
* @param mixed|null $activity The Activity object or WP_Error from processing the inbox request.
*/
\do_action( 'activitypub_handled_inbox', $data, $user_id, $id, $activity );
}
Expand Down
12 changes: 6 additions & 6 deletions includes/handler/class-like.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ public static function handle_like( $like, $user_id ) {
}

/**
* Fires after a Like has been handled.
* Fires after an ActivityPub Like activity has been handled.
*
* @param array $like The Activity array.
* @param int $user_id The ID of the local blog user.
* @param mixed $state The state of the reaction.
* @param mixed $reaction The reaction object.
* @param array $like The ActivityPub activity data.
* @param int|null $user_id The local user ID, or null if not applicable.
* @param mixed $state The state/result of the operation (e.g., comment ID, WP_Error, or status).
* @param mixed|null $reaction The WP_Comment object of the created like comment, or null if creation failed.
*/
do_action( 'activitypub_handled_like', $like, $user_id, $state, $reaction );
\do_action( 'activitypub_handled_like', $like, $user_id, $state, $reaction );
}

/**
Expand Down
Loading