Skip to content

Commit d84d147

Browse files
authored
Improved recipient handling for clarity and added better inbox support (#2210)
1 parent 7572b6f commit d84d147

File tree

7 files changed

+667
-61
lines changed

7 files changed

+667
-61
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: changed
3+
4+
Improved recipient handling for clarity and improved visibility handling of activities.

includes/functions.php

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -525,40 +525,60 @@ function extract_recipients_from_activity( $data ) {
525525
$recipient_items = array();
526526

527527
foreach ( array( 'to', 'bto', 'cc', 'bcc', 'audience' ) as $i ) {
528-
if ( array_key_exists( $i, $data ) ) {
529-
if ( is_array( $data[ $i ] ) ) {
530-
$recipient = $data[ $i ];
531-
} else {
532-
$recipient = array( $data[ $i ] );
533-
}
534-
$recipient_items = array_merge( $recipient_items, $recipient );
535-
}
536-
537-
if ( is_array( $data['object'] ) && array_key_exists( $i, $data['object'] ) ) {
538-
if ( is_array( $data['object'][ $i ] ) ) {
539-
$recipient = $data['object'][ $i ];
540-
} else {
541-
$recipient = array( $data['object'][ $i ] );
542-
}
543-
$recipient_items = array_merge( $recipient_items, $recipient );
544-
}
528+
$recipient_items = \array_merge( $recipient_items, extract_recipients_from_activity_property( $i, $data ) );
545529
}
546530

531+
return \array_unique( $recipient_items );
532+
}
533+
534+
/**
535+
* Extract recipient URLs from a specific property of an Activity object.
536+
*
537+
* @param string $property The property to extract recipients from (e.g., 'to', 'cc').
538+
* @param array $data The Activity object as array.
539+
*
540+
* @return array The list of user URLs.
541+
*/
542+
function extract_recipients_from_activity_property( $property, $data ) {
547543
$recipients = array();
548544

549-
// Flatten array.
550-
foreach ( $recipient_items as $recipient ) {
551-
if ( is_array( $recipient ) ) {
552-
// Check if recipient is an object.
553-
if ( array_key_exists( 'id', $recipient ) ) {
554-
$recipients[] = $recipient['id'];
555-
}
556-
} else {
557-
$recipients[] = $recipient;
558-
}
545+
if ( ! empty( $data[ $property ] ) ) {
546+
$recipients = $data[ $property ];
547+
} elseif ( ! empty( $data['object'][ $property ] ) ) {
548+
$recipients = $data['object'][ $property ];
549+
}
550+
551+
$recipients = \array_map( '\Activitypub\object_to_uri', (array) $recipients );
552+
553+
return \array_unique( \array_filter( $recipients ) );
554+
}
555+
556+
/**
557+
* Determine the visibility of the activity based on its recipients.
558+
*
559+
* @param array $activity The activity data.
560+
*
561+
* @return string The visibility level: 'public', 'private', or 'direct'.
562+
*/
563+
function get_activity_visibility( $activity ) {
564+
// Set default visibility for specific activity types.
565+
if ( ! empty( $activity['type'] ) && in_array( $activity['type'], array( 'Accept', 'Delete', 'Follow', 'Reject', 'Undo' ), true ) ) {
566+
return ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE;
567+
}
568+
569+
// Check 'to' field for public visibility.
570+
$to = extract_recipients_from_activity_property( 'to', $activity );
571+
if ( ! empty( array_intersect( $to, ACTIVITYPUB_PUBLIC_AUDIENCE_IDENTIFIERS ) ) ) {
572+
return ACTIVITYPUB_CONTENT_VISIBILITY_PUBLIC;
573+
}
574+
575+
// Check 'cc' field for quiet public visibility.
576+
$cc = extract_recipients_from_activity_property( 'cc', $activity );
577+
if ( ! empty( array_intersect( $cc, ACTIVITYPUB_PUBLIC_AUDIENCE_IDENTIFIERS ) ) ) {
578+
return ACTIVITYPUB_CONTENT_VISIBILITY_QUIET_PUBLIC;
559579
}
560580

561-
return array_unique( $recipients );
581+
return ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE;
562582
}
563583

564584
/**
@@ -696,7 +716,7 @@ function url_to_commentid( $url ) {
696716
*
697717
* @param array|string $data The ActivityPub object.
698718
*
699-
* @return string The URI of the ActivityPub object
719+
* @return string The URI of the ActivityPub object.
700720
*/
701721
function object_to_uri( $data ) {
702722
// Check whether it is already simple.

includes/handler/class-create.php

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
use Activitypub\Collection\Interactions;
1111

12-
use function Activitypub\is_activity_public;
12+
use function Activitypub\get_activity_visibility;
1313
use function Activitypub\is_activity_reply;
1414
use function Activitypub\is_self_ping;
1515
use function Activitypub\object_id_to_comment;
@@ -22,19 +22,8 @@ class Create {
2222
* Initialize the class, registering WordPress hooks.
2323
*/
2424
public static function init() {
25-
\add_action(
26-
'activitypub_inbox_create',
27-
array( self::class, 'handle_create' ),
28-
10,
29-
3
30-
);
31-
32-
\add_filter(
33-
'activitypub_validate_object',
34-
array( self::class, 'validate_object' ),
35-
10,
36-
3
37-
);
25+
\add_action( 'activitypub_inbox_create', array( self::class, 'handle_create' ), 10, 3 );
26+
\add_filter( 'activitypub_validate_object', array( self::class, 'validate_object' ), 10, 3 );
3827
}
3928

4029
/**
@@ -47,7 +36,7 @@ public static function init() {
4736
public static function handle_create( $activity, $user_id, $activity_object = null ) {
4837
// Check if Activity is public or not.
4938
if (
50-
! is_activity_public( $activity ) ||
39+
ACTIVITYPUB_CONTENT_VISIBILITY_PRIVATE === get_activity_visibility( $activity ) ||
5140
! is_activity_reply( $activity )
5241
) {
5342
return;

includes/rest/class-inbox-controller.php

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -149,23 +149,9 @@ public function create_item( $request ) {
149149
*/
150150
do_action( 'activitypub_rest_inbox_disallowed', $data, null, $type, $activity );
151151
} else {
152-
$recipients = extract_recipients_from_activity( $data );
153-
154-
foreach ( $recipients as $recipient ) {
155-
if ( ! is_same_domain( $recipient ) ) {
156-
continue;
157-
}
158-
159-
$user_id = Actors::get_id_by_various( $recipient );
160-
161-
if ( \is_wp_error( $user_id ) ) {
162-
continue;
163-
}
164-
165-
if ( ! user_can_activitypub( $user_id ) ) {
166-
continue;
167-
}
152+
$recipients = $this->get_local_recipients( $data );
168153

154+
foreach ( $recipients as $user_id ) {
169155
// Check user-specific blocks for this recipient.
170156
if ( Moderation::activity_is_blocked_for_user( $activity, $user_id ) ) {
171157
/**
@@ -288,4 +274,37 @@ public function get_item_schema() {
288274

289275
return $this->add_additional_fields_schema( $this->schema );
290276
}
277+
278+
/**
279+
* Extract recipients from the given Activity.
280+
*
281+
* @param array $activity The activity data.
282+
*
283+
* @return array An array of user IDs who are the recipients of the activity.
284+
*/
285+
private function get_local_recipients( $activity ) {
286+
$recipients = extract_recipients_from_activity( $activity );
287+
$user_ids = array();
288+
289+
foreach ( $recipients as $recipient ) {
290+
291+
if ( ! is_same_domain( $recipient ) ) {
292+
continue;
293+
}
294+
295+
$user_id = Actors::get_id_by_resource( $recipient );
296+
297+
if ( \is_wp_error( $user_id ) ) {
298+
continue;
299+
}
300+
301+
if ( ! user_can_activitypub( $user_id ) ) {
302+
continue;
303+
}
304+
305+
$user_ids[] = $user_id;
306+
}
307+
308+
return $user_ids;
309+
}
291310
}

0 commit comments

Comments
 (0)