@@ -858,6 +858,195 @@ public function test_deduplicate_only_matches_specific_guid() {
858858 $ this ->assertEquals ( 2 , $ count_second , 'Should still have two posts with second-activity GUID (not deduplicated) ' );
859859 }
860860
861+ /**
862+ * Test adding activity when object is an array.
863+ *
864+ * This test verifies that the inbox can handle activities where get_object()
865+ * returns an array instead of an object, which can happen with certain
866+ * ActivityPub implementations.
867+ *
868+ * @covers ::add
869+ */
870+ public function test_add_activity_with_array_object () {
871+ // Create an activity with an array as the object.
872+ $ activity = new Activity ();
873+ $ activity ->set_id ( 'https://remote.example.com/activities/array-object ' );
874+ $ activity ->set_type ( 'Create ' );
875+ $ activity ->set_actor ( 'https://remote.example.com/users/testuser ' );
876+
877+ // Set object as an array (this can happen with certain implementations).
878+ $ activity ->set_object (
879+ array (
880+ 'id ' => 'https://remote.example.com/objects/array-test ' ,
881+ 'type ' => 'Note ' ,
882+ 'content ' => 'Test content ' ,
883+ )
884+ );
885+
886+ $ user_id = 1 ;
887+
888+ // Add activity to inbox - should not throw an error.
889+ $ inbox_id = Inbox::add ( $ activity , $ user_id );
890+
891+ $ this ->assertIsInt ( $ inbox_id );
892+ $ this ->assertGreaterThan ( 0 , $ inbox_id );
893+
894+ // Verify the post was created with empty title (since array doesn't have get_name()).
895+ $ post = \get_post ( $ inbox_id );
896+ $ this ->assertInstanceOf ( 'WP_Post ' , $ post );
897+ $ this ->assertEquals ( Inbox::POST_TYPE , $ post ->post_type );
898+
899+ // Post title should be "[Create] " (activity type with no object title).
900+ $ this ->assertStringStartsWith ( '[Create] ' , $ post ->post_title );
901+ }
902+
903+ /**
904+ * Test adding Flag activity with array of URLs as object.
905+ *
906+ * This test verifies that the inbox can handle Flag activities (used for
907+ * reporting content) where the object is an array of URLs, which is a
908+ * real-world scenario from Mastodon moderation reports.
909+ *
910+ * @covers ::add
911+ */
912+ public function test_add_flag_activity_with_url_array () {
913+ // Create a Flag activity similar to moderation reports.
914+ $ activity = new Activity ();
915+ $ activity ->set_id ( 'https://remote.example.com/activities/flag-report ' );
916+ $ activity ->set_type ( 'Flag ' );
917+ $ activity ->set_actor ( 'https://remote.example.com/users/reporter ' );
918+ $ activity ->set_content ( '' ); // Flag activities often have empty content.
919+
920+ // Set object as an array of URLs (actor being reported + content being reported).
921+ $ activity ->set_object (
922+ array (
923+ 'https://example.org/users/reported-user ' ,
924+ 'https://example.org/posts/12345 ' ,
925+ )
926+ );
927+
928+ $ user_id = 1 ;
929+
930+ // Add activity to inbox - should not throw an error despite array object.
931+ $ inbox_id = Inbox::add ( $ activity , $ user_id );
932+
933+ $ this ->assertIsInt ( $ inbox_id );
934+ $ this ->assertGreaterThan ( 0 , $ inbox_id );
935+
936+ // Verify the post was created.
937+ $ post = \get_post ( $ inbox_id );
938+ $ this ->assertInstanceOf ( 'WP_Post ' , $ post );
939+ $ this ->assertEquals ( Inbox::POST_TYPE , $ post ->post_type );
940+
941+ // Post title should be "[Flag] " (activity type with no object title from array).
942+ $ this ->assertStringStartsWith ( '[Flag] ' , $ post ->post_title );
943+ }
944+
945+ /**
946+ * Test adding activity when object is null.
947+ *
948+ * @covers ::add
949+ */
950+ public function test_add_activity_with_null_object () {
951+ $ activity = new Activity ();
952+ $ activity ->set_id ( 'https://remote.example.com/activities/null-object ' );
953+ $ activity ->set_type ( 'Delete ' );
954+ $ activity ->set_actor ( 'https://remote.example.com/users/testuser ' );
955+ // Don't set any object - it will be null.
956+
957+ $ inbox_id = Inbox::add ( $ activity , 1 );
958+
959+ $ this ->assertIsInt ( $ inbox_id );
960+ $ this ->assertGreaterThan ( 0 , $ inbox_id );
961+
962+ // Post title should be "[Delete] " with no object title.
963+ $ post = \get_post ( $ inbox_id );
964+ $ this ->assertStringStartsWith ( '[Delete] ' , $ post ->post_title );
965+ }
966+
967+ /**
968+ * Test adding activity when object is a string URL.
969+ *
970+ * @covers ::add
971+ */
972+ public function test_add_activity_with_string_object () {
973+ // Create a post to reference.
974+ $ post_id = self ::factory ()->post ->create (
975+ array (
976+ 'post_title ' => 'Referenced Post ' ,
977+ 'post_status ' => 'publish ' ,
978+ )
979+ );
980+ $ post_url = \get_permalink ( $ post_id );
981+
982+ $ activity = new Activity ();
983+ $ activity ->set_id ( 'https://remote.example.com/activities/string-object ' );
984+ $ activity ->set_type ( 'Like ' );
985+ $ activity ->set_actor ( 'https://remote.example.com/users/testuser ' );
986+ $ activity ->set_object ( $ post_url ); // String URL.
987+
988+ $ inbox_id = Inbox::add ( $ activity , 1 );
989+
990+ $ this ->assertIsInt ( $ inbox_id );
991+
992+ // Post title should include the referenced post title.
993+ $ post = \get_post ( $ inbox_id );
994+ $ this ->assertStringContainsString ( 'Referenced Post ' , $ post ->post_title );
995+ }
996+
997+ /**
998+ * Test adding activity with object that has name property.
999+ *
1000+ * @covers ::add
1001+ */
1002+ public function test_add_activity_with_object_name () {
1003+ $ activity = new Activity ();
1004+ $ activity ->set_id ( 'https://remote.example.com/activities/object-name ' );
1005+ $ activity ->set_type ( 'Create ' );
1006+ $ activity ->set_actor ( 'https://remote.example.com/users/testuser ' );
1007+
1008+ $ object = new Base_Object ();
1009+ $ object ->set_id ( 'https://remote.example.com/objects/named ' );
1010+ $ object ->set_type ( 'Note ' );
1011+ $ object ->set_name ( 'My Note Title ' );
1012+ $ object ->set_content ( 'This is the content ' );
1013+ $ activity ->set_object ( $ object );
1014+
1015+ $ inbox_id = Inbox::add ( $ activity , 1 );
1016+
1017+ $ this ->assertIsInt ( $ inbox_id );
1018+
1019+ // Post title should include the object name.
1020+ $ post = \get_post ( $ inbox_id );
1021+ $ this ->assertStringContainsString ( 'My Note Title ' , $ post ->post_title );
1022+ }
1023+
1024+ /**
1025+ * Test adding activity with object that has content but no name.
1026+ *
1027+ * @covers ::add
1028+ */
1029+ public function test_add_activity_with_object_content_no_name () {
1030+ $ activity = new Activity ();
1031+ $ activity ->set_id ( 'https://remote.example.com/activities/object-content ' );
1032+ $ activity ->set_type ( 'Create ' );
1033+ $ activity ->set_actor ( 'https://remote.example.com/users/testuser ' );
1034+
1035+ $ object = new Base_Object ();
1036+ $ object ->set_id ( 'https://remote.example.com/objects/content-only ' );
1037+ $ object ->set_type ( 'Note ' );
1038+ $ object ->set_content ( 'This is the content without a name ' );
1039+ $ activity ->set_object ( $ object );
1040+
1041+ $ inbox_id = Inbox::add ( $ activity , 1 );
1042+
1043+ $ this ->assertIsInt ( $ inbox_id );
1044+
1045+ // Post title should include part of the content (since no name).
1046+ $ post = \get_post ( $ inbox_id );
1047+ $ this ->assertStringContainsString ( 'This is the content ' , $ post ->post_title );
1048+ }
1049+
8611050 /**
8621051 * Test adding Like activity with trailing slash in object URL.
8631052 *
0 commit comments