Skip to content

Commit 074e562

Browse files
committed
fix: keep documents with a null required attribute updatable
A document stored before an attribute became required holds null for it, and updates validate the merged document, so every update of that document failed with "Missing required attribute". When the current document already holds null, the attribute may stay null on update. Creating a document without it, or clearing a stored value, still fails.
1 parent ef5d6e5 commit 074e562

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

‎src/Database/Validator/Structure.php‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,11 @@ protected function checkForAllRequiredValues(array $structure, array $attributes
267267
$keys[$name] = $attribute; // List of allowed attributes to help find unknown ones
268268

269269
if ($required && !isset($structure[$name])) {
270+
// Documents stored before the attribute became required hold null, and may keep it
271+
if ($this->currentDocument !== null && $this->currentDocument->getAttribute($name) === null) {
272+
continue;
273+
}
274+
270275
$this->message = 'Missing required attribute "'.$name.'"';
271276
return false;
272277
}
@@ -333,6 +338,10 @@ protected function checkForInvalidAttributeValues(Document $document, array $str
333338
continue;
334339
}
335340

341+
if (is_null($value) && $this->currentDocument !== null && $this->currentDocument->getAttribute($key) === null) {
342+
continue;
343+
}
344+
336345
if ($type === Database::VAR_RELATIONSHIP) {
337346
continue;
338347
}

‎tests/unit/Validator/StructureTest.php‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,38 @@ public function testRequiredKeys(): void
242242
$this->assertEquals('Invalid document structure: Missing required attribute "title"', $validator->getDescription());
243243
}
244244

245+
public function testRequiredKeyStoredAsNull(): void
246+
{
247+
$document = [
248+
'$collection' => ID::custom('posts'),
249+
'description' => 'Demo description',
250+
'rating' => 5,
251+
'price' => 1.99,
252+
'published' => true,
253+
'feedback' => 'team@appwrite.io',
254+
'$createdAt' => '2000-04-01T12:00:00.000+00:00',
255+
'$updatedAt' => '2000-04-01T12:00:00.000+00:00'
256+
];
257+
258+
$validator = new Structure(
259+
new Document($this->collection),
260+
Database::VAR_INTEGER,
261+
currentDocument: new Document(['title' => null])
262+
);
263+
264+
$this->assertTrue($validator->isValid(new Document($document)), $validator->getDescription());
265+
$this->assertTrue($validator->isValid(new Document([...$document, 'title' => null])), $validator->getDescription());
266+
267+
$validator = new Structure(
268+
new Document($this->collection),
269+
Database::VAR_INTEGER,
270+
currentDocument: new Document(['title' => 'My Title'])
271+
);
272+
273+
$this->assertFalse($validator->isValid(new Document([...$document, 'title' => null])));
274+
$this->assertEquals('Invalid document structure: Missing required attribute "title"', $validator->getDescription());
275+
}
276+
245277
public function testNullValues(): void
246278
{
247279
$validator = new Structure(

0 commit comments

Comments
 (0)