Skip to content

Commit da31aff

Browse files
committed
Handle reverse missing optional cases
1 parent 477cb44 commit da31aff

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

src/Database/Database.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4980,18 +4980,21 @@ public function createOrUpdateDocumentsWithIncrease(
49804980
if ($old->isEmpty()) {
49814981
$createdAt = $document->getCreatedAt();
49824982
$document->setAttribute('$createdAt', empty($createdAt) || !$this->preserveDates ? $time : $createdAt);
4983-
4984-
// Force matching optional parameter sets
4985-
// Doesn't use decode as that intentionally skips null defaults to reduce payload size
4986-
foreach ($collectionAttributes as $attr) {
4987-
if (!$attr->getAttribute('required') && !$document->isSet($attr['$id'])) {
4988-
$document->setAttribute($attr['$id'], $attr['default'] ?? null);
4989-
}
4990-
}
49914983
} else {
49924984
$document['$createdAt'] = $old->getCreatedAt();
49934985
}
49944986

4987+
// Force matching optional parameter sets
4988+
// Doesn't use decode as that intentionally skips null defaults to reduce payload size
4989+
foreach ($collectionAttributes as $attr) {
4990+
if (!$attr->getAttribute('required') && !\array_key_exists($attr['$id'], (array)$document)) {
4991+
$document->setAttribute(
4992+
$attr['$id'],
4993+
$old->getAttribute($attr['$id'], ($attr['default'] ?? null))
4994+
);
4995+
}
4996+
}
4997+
49954998
if (!$updatesPermissions) {
49964999
$document->setAttribute('$permissions', $old->getPermissions());
49975000
}

tests/e2e/Adapter/Scopes/DocumentTests.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,13 +621,15 @@ public function testUpsertDocumentsAttributeMismatch(): void
621621
'first' => 'second',
622622
]);
623623

624+
// Ensure missing optionals on new document is allowed
624625
$docs = $database->createOrUpdateDocuments(__FUNCTION__, [
625626
$existingDocument->setAttribute('first', 'updated'),
626627
$newDocument,
627628
]);
628629

629630
$this->assertEquals(2, $docs);
630631
$this->assertEquals('updated', $existingDocument->getAttribute('first'));
632+
$this->assertEquals('last', $existingDocument->getAttribute('last'));
631633
$this->assertEquals('second', $newDocument->getAttribute('first'));
632634
$this->assertEquals('', $newDocument->getAttribute('last'));
633635

@@ -640,6 +642,36 @@ public function testUpsertDocumentsAttributeMismatch(): void
640642
} catch (Throwable $e) {
641643
$this->assertTrue($e instanceof StructureException, $e->getMessage());
642644
}
645+
646+
// Ensure missing optionals on existing document is allowed
647+
$docs = $database->createOrUpdateDocuments(__FUNCTION__, [
648+
$existingDocument
649+
->setAttribute('first', 'first')
650+
->removeAttribute('last'),
651+
$newDocument
652+
->setAttribute('last', 'last')
653+
]);
654+
655+
$this->assertEquals(2, $docs);
656+
$this->assertEquals('first', $existingDocument->getAttribute('first'));
657+
$this->assertEquals('last', $existingDocument->getAttribute('last'));
658+
$this->assertEquals('second', $newDocument->getAttribute('first'));
659+
$this->assertEquals('last', $newDocument->getAttribute('last'));
660+
661+
// Ensure set null on existing document is allowed
662+
$docs = $database->createOrUpdateDocuments(__FUNCTION__, [
663+
$existingDocument
664+
->setAttribute('first', 'first')
665+
->setAttribute('last', null),
666+
$newDocument
667+
->setAttribute('last', 'last')
668+
]);
669+
670+
$this->assertEquals(1, $docs);
671+
$this->assertEquals('first', $existingDocument->getAttribute('first'));
672+
$this->assertEquals(null, $existingDocument->getAttribute('last'));
673+
$this->assertEquals('second', $newDocument->getAttribute('first'));
674+
$this->assertEquals('last', $newDocument->getAttribute('last'));
643675
}
644676

645677
public function testUpsertDocumentsNoop(): void

0 commit comments

Comments
 (0)