diff --git a/includes/class-activity-dispatcher.php b/includes/class-activity-dispatcher.php index a130ba3..4385ebe 100644 --- a/includes/class-activity-dispatcher.php +++ b/includes/class-activity-dispatcher.php @@ -30,14 +30,8 @@ class Activity_Dispatcher { $activitypub_activity = new \Activitypub\Model\Activity( 'Create', \Activitypub\Model\Activity::TYPE_FULL ); $activitypub_activity->from_post( $activitypub_post ); - $sent = array(); - foreach ( \Activitypub\get_follower_inboxes( $user_id ) as $inbox => $to ) { - $sent[ $to ] = true; - $activitypub_activity->set_to( $to ); - $activity = $activitypub_activity->to_json(); // phpcs:ignore + $inboxes = \Activitypub\get_follower_inboxes( $user_id ); - \Activitypub\safe_remote_post( $inbox, $activity, $user_id ); - } $followers_url = \get_rest_url( null, '/activitypub/1.0/users/' . intval( $user_id ) . '/followers' ); foreach ( $activitypub_activity->get_cc() as $cc ) { if ( $cc === $followers_url ) { @@ -47,21 +41,27 @@ class Activity_Dispatcher { if ( ! $inbox || \is_wp_error( $inbox ) ) { continue; } - if ( isset( $sent[ $cc ] ) ) { - continue; + // init array if empty + if ( ! isset( $inboxes[ $inbox ] ) ) { + $inboxes[ $inbox ] = array(); } - $sent[ $cc ] = true; - $activity = $activitypub_activity->to_json(); // phpcs:ignore + $inboxes[ $inbox ][] = $cc; + } + + foreach ( $inboxes as $inbox => $to ) { + $to = array_unique( $to ); + $activitypub_activity->set_to( $to ); + $activity = $activitypub_activity->to_json(); \Activitypub\safe_remote_post( $inbox, $activity, $user_id ); } } - /** - * Send "update" activities. - * - * @param \Activitypub\Model\Post $activitypub_post - */ + /** + * Send "update" activities. + * + * @param \Activitypub\Model\Post $activitypub_post + */ public static function send_update_activity( $activitypub_post ) { // get latest version of post $user_id = $activitypub_post->get_post_author(); @@ -77,11 +77,11 @@ class Activity_Dispatcher { } } - /** - * Send "delete" activities. - * - * @param \Activitypub\Model\Post $activitypub_post - */ + /** + * Send "delete" activities. + * + * @param \Activitypub\Model\Post $activitypub_post + */ public static function send_delete_activity( $activitypub_post ) { // get latest version of post $user_id = $activitypub_post->get_post_author(); diff --git a/tests/test-class-activitypub-activity-dispatcher.php b/tests/test-class-activitypub-activity-dispatcher.php index 228ee6d..d34a24e 100644 --- a/tests/test-class-activitypub-activity-dispatcher.php +++ b/tests/test-class-activitypub-activity-dispatcher.php @@ -1,6 +1,44 @@ array( + 'url' => 'https://example.org/users/username', + 'inbox' => 'https://example.org/users/username/inbox', + 'name' => 'username', + ), + 'jon@example.com' => array( + 'url' => 'https://example.com/author/jon', + 'inbox' => 'https://example.com/author/jon/inbox', + 'name' => 'jon', + ), + ); + + public function test_dispatch_activity() { + $followers = array( 'https://example.com/author/jon', 'https://example.org/users/username' ); + \update_user_meta( 1, 'activitypub_followers', $followers ); + + $post = \wp_insert_post( + array( + 'post_author' => 1, + 'post_content' => 'hello', + ) + ); + + $pre_http_request = new MockAction(); + add_filter( 'pre_http_request', array( $pre_http_request, 'filter' ), 10, 3 ); + + $activitypub_post = new \Activitypub\Model\Post( $post ); + \Activitypub\Activity_Dispatcher::send_post_activity( $activitypub_post ); + + $this->assertSame( 2, $pre_http_request->get_call_count() ); + $all_args = $pre_http_request->get_args(); + $first_call_args = array_shift( $all_args ); + $this->assertEquals( 'https://example.com/author/jon/inbox', $first_call_args[2] ); + $second_call_args = array_shift( $all_args ); + $this->assertEquals( 'https://example.org/users/username/inbox', $second_call_args[2] ); + + remove_filter( 'pre_http_request', array( $pre_http_request, 'filter' ), 10 ); + } public function test_dispatch_mentions() { $post = \wp_insert_post( array( @@ -41,21 +79,11 @@ class Test_Activitypub_Activity_Dispatcher extends WP_UnitTestCase { public function set_up() { parent::set_up(); - - add_filter( 'pre_http_request', array( get_called_class(), 'pre_http_request' ), 10, 3 ); - add_filter( 'http_response', array( get_called_class(), 'http_response' ), 10, 3 ); - add_filter( 'http_request_host_is_external', array( get_called_class(), 'http_request_host_is_external' ), 10, 2 ); - add_filter( 'http_request_args', array( get_called_class(), 'http_request_args' ), 10, 2 ); add_filter( 'pre_get_remote_metadata_by_actor', array( get_called_class(), 'pre_get_remote_metadata_by_actor' ), 10, 2 ); - _delete_all_posts(); } public function tear_down() { - remove_filter( 'pre_http_request', array( get_called_class(), 'pre_http_request' ) ); - remove_filter( 'http_response', array( get_called_class(), 'http_response' ) ); - remove_filter( 'http_request_host_is_external', array( get_called_class(), 'http_request_host_is_external' ) ); - remove_filter( 'http_request_args', array( get_called_class(), 'http_request_args' ) ); remove_filter( 'pre_get_remote_metadata_by_actor', array( get_called_class(), 'pre_get_remote_metadata_by_actor' ) ); parent::tear_down(); } @@ -64,6 +92,11 @@ class Test_Activitypub_Activity_Dispatcher extends WP_UnitTestCase { if ( isset( self::$users[ $actor ] ) ) { return self::$users[ $actor ]; } + foreach ( self::$users as $username => $data ) { + if ( $data['url'] === $actor ) { + return $data; + } + } return $pre; } @@ -79,6 +112,7 @@ class Test_Activitypub_Activity_Dispatcher extends WP_UnitTestCase { } return $args; } + public static function pre_http_request( $preempt, $request, $url ) { return array( 'headers' => array(