@@ -1939,4 +1939,158 @@ public function testDeleteDocumentsRelationshipErrorDoesNotDeleteParent_ManyToMa
19391939 $ database ->deleteCollection ($ parentCollection );
19401940 $ database ->deleteCollection ($ childCollection );
19411941 }
1942+
1943+ public function testPartialUpdateManyToManyBothSides (): void
1944+ {
1945+ /** @var Database $database */
1946+ $ database = static ::getDatabase ();
1947+
1948+ if (!$ database ->getAdapter ()->getSupportForRelationships ()) {
1949+ $ this ->expectNotToPerformAssertions ();
1950+ return ;
1951+ }
1952+
1953+ $ database ->createCollection ('partial_students ' );
1954+ $ database ->createCollection ('partial_courses ' );
1955+
1956+ $ database ->createAttribute ('partial_students ' , 'name ' , Database::VAR_STRING , 255 , true );
1957+ $ database ->createAttribute ('partial_students ' , 'grade ' , Database::VAR_STRING , 10 , false );
1958+ $ database ->createAttribute ('partial_courses ' , 'title ' , Database::VAR_STRING , 255 , true );
1959+ $ database ->createAttribute ('partial_courses ' , 'credits ' , Database::VAR_INTEGER , 0 , false );
1960+
1961+ $ database ->createRelationship (
1962+ collection: 'partial_students ' ,
1963+ relatedCollection: 'partial_courses ' ,
1964+ type: Database::RELATION_MANY_TO_MANY ,
1965+ twoWay: true ,
1966+ id: 'partial_courses ' ,
1967+ twoWayKey: 'partial_students '
1968+ );
1969+
1970+ // Create student with courses
1971+ $ database ->createDocument ('partial_students ' , new Document ([
1972+ '$id ' => 'student1 ' ,
1973+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
1974+ 'name ' => 'David ' ,
1975+ 'grade ' => 'A ' ,
1976+ 'partial_courses ' => [
1977+ ['$id ' => 'course1 ' , '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())], 'title ' => 'Math ' , 'credits ' => 3 ],
1978+ ['$id ' => 'course2 ' , '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())], 'title ' => 'Science ' , 'credits ' => 4 ],
1979+ ],
1980+ ]));
1981+
1982+ // Partial update from student side - update grade only, preserve courses
1983+ $ database ->updateDocument ('partial_students ' , 'student1 ' , new Document ([
1984+ '$id ' => 'student1 ' ,
1985+ '$collection ' => 'partial_students ' ,
1986+ 'grade ' => 'A+ ' ,
1987+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
1988+ ]));
1989+
1990+ $ student = $ database ->getDocument ('partial_students ' , 'student1 ' );
1991+ $ this ->assertEquals ('David ' , $ student ->getAttribute ('name ' ), 'Name should be preserved ' );
1992+ $ this ->assertEquals ('A+ ' , $ student ->getAttribute ('grade ' ), 'Grade should be updated ' );
1993+ $ this ->assertCount (2 , $ student ->getAttribute ('partial_courses ' ), 'Courses should be preserved ' );
1994+
1995+ // Partial update from course side - update credits only, preserve students
1996+ $ database ->updateDocument ('partial_courses ' , 'course1 ' , new Document ([
1997+ '$id ' => 'course1 ' ,
1998+ '$collection ' => 'partial_courses ' ,
1999+ 'credits ' => 5 ,
2000+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
2001+ ]));
2002+
2003+ $ course = $ database ->getDocument ('partial_courses ' , 'course1 ' );
2004+ $ this ->assertEquals ('Math ' , $ course ->getAttribute ('title ' ), 'Title should be preserved ' );
2005+ $ this ->assertEquals (5 , $ course ->getAttribute ('credits ' ), 'Credits should be updated ' );
2006+ $ this ->assertCount (1 , $ course ->getAttribute ('partial_students ' ), 'Students should be preserved ' );
2007+
2008+ $ database ->deleteCollection ('partial_students ' );
2009+ $ database ->deleteCollection ('partial_courses ' );
2010+ }
2011+
2012+ public function testPartialUpdateManyToManyWithStringIdsAndDocuments (): void
2013+ {
2014+ /** @var Database $database */
2015+ $ database = static ::getDatabase ();
2016+
2017+ if (!$ database ->getAdapter ()->getSupportForRelationships ()) {
2018+ $ this ->expectNotToPerformAssertions ();
2019+ return ;
2020+ }
2021+
2022+ $ database ->createCollection ('tags ' );
2023+ $ database ->createCollection ('articles ' );
2024+
2025+ $ database ->createAttribute ('tags ' , 'name ' , Database::VAR_STRING , 255 , true );
2026+ $ database ->createAttribute ('tags ' , 'color ' , Database::VAR_STRING , 50 , false );
2027+ $ database ->createAttribute ('articles ' , 'title ' , Database::VAR_STRING , 255 , true );
2028+ $ database ->createAttribute ('articles ' , 'published ' , Database::VAR_BOOLEAN , 0 , false );
2029+
2030+ $ database ->createRelationship (
2031+ collection: 'articles ' ,
2032+ relatedCollection: 'tags ' ,
2033+ type: Database::RELATION_MANY_TO_MANY ,
2034+ twoWay: true ,
2035+ id: 'tags ' ,
2036+ twoWayKey: 'articles '
2037+ );
2038+
2039+ // Create article with tags
2040+ $ database ->createDocument ('articles ' , new Document ([
2041+ '$id ' => 'article1 ' ,
2042+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
2043+ 'title ' => 'Great Article ' ,
2044+ 'published ' => false ,
2045+ 'tags ' => [
2046+ ['$id ' => 'tag1 ' , '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())], 'name ' => 'Tech ' , 'color ' => 'blue ' ],
2047+ ],
2048+ ]));
2049+
2050+ $ database ->createDocument ('tags ' , new Document ([
2051+ '$id ' => 'tag2 ' ,
2052+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
2053+ 'name ' => 'News ' ,
2054+ 'color ' => 'red ' ,
2055+ ]));
2056+
2057+ // Update using STRING IDs
2058+ $ database ->updateDocument ('articles ' , 'article1 ' , new Document ([
2059+ '$id ' => 'article1 ' ,
2060+ '$collection ' => 'articles ' ,
2061+ 'tags ' => ['tag1 ' , 'tag2 ' ], // String IDs
2062+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
2063+ ]));
2064+
2065+ $ article = $ database ->getDocument ('articles ' , 'article1 ' );
2066+ $ this ->assertEquals ('Great Article ' , $ article ->getAttribute ('title ' ));
2067+ $ this ->assertFalse ($ article ->getAttribute ('published ' ));
2068+ $ this ->assertCount (2 , $ article ->getAttribute ('tags ' ));
2069+
2070+ // Update from tag side using DOCUMENT objects
2071+ $ database ->createDocument ('articles ' , new Document ([
2072+ '$id ' => 'article2 ' ,
2073+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
2074+ 'title ' => 'Another Article ' ,
2075+ 'published ' => true ,
2076+ ]));
2077+
2078+ $ database ->updateDocument ('tags ' , 'tag1 ' , new Document ([
2079+ '$id ' => 'tag1 ' ,
2080+ '$collection ' => 'tags ' ,
2081+ 'articles ' => [ // Document objects
2082+ new Document (['$id ' => 'article1 ' ]),
2083+ new Document (['$id ' => 'article2 ' ]),
2084+ ],
2085+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
2086+ ]));
2087+
2088+ $ tag = $ database ->getDocument ('tags ' , 'tag1 ' );
2089+ $ this ->assertEquals ('Tech ' , $ tag ->getAttribute ('name ' ));
2090+ $ this ->assertEquals ('blue ' , $ tag ->getAttribute ('color ' ));
2091+ $ this ->assertCount (2 , $ tag ->getAttribute ('articles ' ));
2092+
2093+ $ database ->deleteCollection ('tags ' );
2094+ $ database ->deleteCollection ('articles ' );
2095+ }
19422096}
0 commit comments