diff --git a/src/Database/Database.php b/src/Database/Database.php index dbe891f20..6524abee6 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -2940,6 +2940,10 @@ public function updateDocument(string $collection, string $id, Document $documen foreach ($document as $key => $value) { // Skip the nested documents as they will be checked later in recursions. if (\array_key_exists($key, $relationships)) { + // No need to compare nested documents more than max depth. + if (count($this->relationshipWriteStack) >= Database::RELATION_MAX_DEPTH - 1) { + continue; + } $relationType = (string) $relationships[$key]['options']['relationType']; $side = (string) $relationships[$key]['options']['side']; diff --git a/tests/Database/Base.php b/tests/Database/Base.php index 18c39e63b..75030e84c 100644 --- a/tests/Database/Base.php +++ b/tests/Database/Base.php @@ -3326,49 +3326,93 @@ public function testNoChangeUpdateDocumentWithRelationWithoutPermission(): void $this->expectNotToPerformAssertions(); return; } + $attribute = new Document([ + '$id' => ID::custom("name"), + 'type' => Database::VAR_STRING, + 'size' => 100, + 'required' => false, + 'default' => null, + 'signed' => false, + 'array' => false, + 'filters' => [], + ]); - static::getDatabase()->createCollection('parentRelationTest'); - static::getDatabase()->createCollection('childRelationTest'); - - static::getDatabase()->createAttribute('parentRelationTest', 'name', Database::VAR_STRING, 255, false); - static::getDatabase()->createAttribute('childRelationTest', 'name', Database::VAR_STRING, 255, false); + $permissions = [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::delete(Role::any()), + ]; + for ($i=1; $i < 6; $i++) { + static::getDatabase()->createCollection("level{$i}", [$attribute], [], $permissions); + } - static::getDatabase()->createRelationship( - collection: 'parentRelationTest', - relatedCollection: 'childRelationTest', - type: Database::RELATION_ONE_TO_MANY, - id: 'children' - ); + for ($i = 1; $i < 5; $i++) { + $collectionId = $i; + $relatedCollectionId = $i+1; + static::getDatabase()->createRelationship( + collection: "level{$collectionId}", + relatedCollection: "level{$relatedCollectionId}", + type: Database::RELATION_ONE_TO_ONE, + id: "level{$relatedCollectionId}" + ); + } // Create document with relationship with nested data - $parent = static::getDatabase()->createDocument('parentRelationTest', new Document([ - '$id' => 'parent1', - '$permissions' => [ - Permission::read(Role::any()), - ], - 'name' => 'Parent 1', - 'children' => [ - [ - '$id' => 'child1', - '$permissions' => [ - Permission::read(Role::any()), + $level1 = static::getDatabase()->createDocument('level1', new Document([ + '$id' => 'level1', + '$permissions' => [], + 'name' => 'Level 1', + 'level2' => [ + '$id' => 'level2', + '$permissions' => [], + 'name' => 'Level 2', + 'level3' => [ + '$id' => 'level3', + '$permissions' => [], + 'name' => 'Level 3', + 'level4' => [ + '$id' => 'level4', + '$permissions' => [], + 'name' => 'Level 4', + 'level5' => [ + '$id' => 'level5', + '$permissions' => [], + 'name' => 'Level 5', + ] ], - 'name' => 'Child 1', ], ], ])); + static::getDatabase()->updateDocument('level1', $level1->getId(), new Document($level1->getArrayCopy())); + $updatedLevel1 = static::getDatabase()->getDocument('level1', $level1->getId()); + $this->assertEquals($level1, $updatedLevel1); - $this->assertEquals(1, \count($parent['children'])); - - $parent->setAttribute('children', ['child1']); + try { + static::getDatabase()->updateDocument('level1', $level1->getId(), $level1->setAttribute('name', 'haha')); + $this->fail('Failed to throw exception'); + } catch(Exception $e) { + $this->assertInstanceOf(AuthorizationException::class, $e); + } + $level1->setAttribute('name', 'Level 1'); + static::getDatabase()->updateCollection('level3', [ + Permission::read(Role::any()), + Permission::create(Role::any()), + Permission::update(Role::any()), + Permission::delete(Role::any()), + ], false); + $level2 = $level1->getAttribute('level2'); + $level3 = $level2->getAttribute('level3'); - $updatedParent = static::getDatabase()->updateDocument('parentRelationTest', 'parent1', $parent); + $level3->setAttribute('name', 'updated value'); + $level2->setAttribute('level3', $level3); + $level1->setAttribute('level2', $level2); - $this->assertEquals($updatedParent->getUpdatedAt(), $parent->getUpdatedAt()); - $this->assertEquals($updatedParent->getAttribute('children')[0]->getUpdatedAt(), $parent->getAttribute('children')[0]->getUpdatedAt()); + $level1 = static::getDatabase()->updateDocument('level1', $level1->getId(), $level1); + $this->assertEquals('updated value', $level1['level2']['level3']['name']); - static::getDatabase()->deleteCollection('parentRelationTest'); - static::getDatabase()->deleteCollection('childRelationTest'); + for ($i=1; $i < 6; $i++) { + static::getDatabase()->deleteCollection("level{$i}"); + } } public function testExceptionAttributeLimit(): void