Skip to content
4 changes: 4 additions & 0 deletions src/Database/Adapter/SQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ public function updateDocuments(string $collection, Document $updates, array $do
$attributes['_updatedAt'] = $updates->getUpdatedAt();
}

if (!empty($updates->getCreatedAt())) {
$attributes['_createdAt'] = $updates->getCreatedAt();
}

if (!empty($updates->getPermissions())) {
$attributes['_permissions'] = json_encode($updates->getPermissions());
}
Expand Down
45 changes: 25 additions & 20 deletions src/Database/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -3604,8 +3604,8 @@ public function createDocument(string $collection, Document $document): Document
$document
->setAttribute('$id', empty($document->getId()) ? ID::unique() : $document->getId())
->setAttribute('$collection', $collection->getId())
->setAttribute('$createdAt', empty($createdAt) || !$this->preserveDates ? $time : $createdAt)
->setAttribute('$updatedAt', empty($updatedAt) || !$this->preserveDates ? $time : $updatedAt);
->setAttribute('$createdAt', ($createdAt === null || !$this->preserveDates) ? $time : $createdAt)
->setAttribute('$updatedAt', ($updatedAt === null || !$this->preserveDates) ? $time : $updatedAt);

if ($this->adapter->getSharedTables()) {
if ($this->adapter->getTenantPerDocument()) {
Expand Down Expand Up @@ -3703,8 +3703,8 @@ public function createDocuments(
$document
->setAttribute('$id', empty($document->getId()) ? ID::unique() : $document->getId())
->setAttribute('$collection', $collection->getId())
->setAttribute('$createdAt', empty($createdAt) || !$this->preserveDates ? $time : $createdAt)
->setAttribute('$updatedAt', empty($updatedAt) || !$this->preserveDates ? $time : $updatedAt);
->setAttribute('$createdAt', ($createdAt === null || !$this->preserveDates) ? $time : $createdAt)
->setAttribute('$updatedAt', ($updatedAt === null || !$this->preserveDates) ? $time : $updatedAt);

if ($this->adapter->getSharedTables()) {
if ($this->adapter->getTenantPerDocument()) {
Expand Down Expand Up @@ -4119,10 +4119,11 @@ public function updateDocument(string $collection, string $id, Document $documen

$skipPermissionsUpdate = ($originalPermissions === $currentPermissions);
}
$createdAt = $document->getCreatedAt();

$document = \array_merge($old->getArrayCopy(), $document->getArrayCopy());
$document['$collection'] = $old->getAttribute('$collection'); // Make sure user doesn't switch collection ID
$document['$createdAt'] = $old->getCreatedAt(); // Make sure user doesn't switch createdAt
$document['$createdAt'] = ($createdAt === null || !$this->preserveDates) ? $old->getCreatedAt() : $createdAt;

if ($this->adapter->getSharedTables()) {
$document['$tenant'] = $old->getTenant(); // Make sure user doesn't switch tenant
Expand Down Expand Up @@ -4251,7 +4252,7 @@ public function updateDocument(string $collection, string $id, Document $documen

if ($shouldUpdate) {
$updatedAt = $document->getUpdatedAt();
$document->setAttribute('$updatedAt', empty($updatedAt) || !$this->preserveDates ? $time : $updatedAt);
$document->setAttribute('$updatedAt', ($updatedAt === null || !$this->preserveDates) ? $time : $updatedAt);
}

// Check if document was updated after the request timestamp
Expand Down Expand Up @@ -4365,21 +4366,21 @@ public function updateDocuments(
if (!empty($cursor) && $cursor->getCollection() !== $collection->getId()) {
throw new DatabaseException("Cursor document must be from the same Collection.");
}

unset($updates['$id']);
unset($updates['$createdAt']);
unset($updates['$tenant']);

if (($updates->getCreatedAt() === null || !$this->preserveDates)) {
unset($updates['$createdAt']);
} else {
$updates['$createdAt'] = $updates->getCreatedAt();
}
if ($this->adapter->getSharedTables()) {
$updates['$tenant'] = $this->adapter->getTenant();
}

if (!$this->preserveDates) {
$updates['$updatedAt'] = DateTime::now();
}
$updatedAt = $updates->getUpdatedAt();
$updates['$updatedAt'] = ($updatedAt === null || !$this->preserveDates) ? DateTime::now() : $updatedAt;

$updates = $this->encode($collection, $updates);

// Check new document structure
$validator = new PartialStructure(
$collection,
Expand Down Expand Up @@ -4990,14 +4991,14 @@ public function createOrUpdateDocumentsWithIncrease(
$document
->setAttribute('$id', empty($document->getId()) ? ID::unique() : $document->getId())
->setAttribute('$collection', $collection->getId())
->setAttribute('$updatedAt', empty($updatedAt) || !$this->preserveDates ? $time : $updatedAt)
->setAttribute('$updatedAt', ($updatedAt === null || !$this->preserveDates) ? $time : $updatedAt)
->removeAttribute('$sequence');

if ($old->isEmpty()) {
$createdAt = $document->getCreatedAt();
$document->setAttribute('$createdAt', empty($createdAt) || !$this->preserveDates ? $time : $createdAt);
$createdAt = $document->getCreatedAt();
if ($createdAt === null || !$this->preserveDates) {
$document->setAttribute('$createdAt', $old->isEmpty() ? $time : $old->getCreatedAt());
} else {
$document['$createdAt'] = $old->getCreatedAt();
$document->setAttribute('$createdAt', $createdAt);
}

// Force matching optional parameter sets
Expand Down Expand Up @@ -6312,7 +6313,7 @@ public static function addFilter(string $name, callable $encode, callable $decod
public function encode(Document $collection, Document $document): Document
{
$attributes = $collection->getAttribute('attributes', []);

$internalDateAttributes = ['$createdAt','$updatedAt'];
foreach ($this->getInternalAttributes() as $attribute) {
$attributes[] = $attribute;
}
Expand All @@ -6324,6 +6325,11 @@ public function encode(Document $collection, Document $document): Document
$filters = $attribute['filters'] ?? [];
$value = $document->getAttribute($key);

if (in_array($key, $internalDateAttributes) && is_string($value) && empty($value)) {
$document->setAttribute($key, null);
continue;
}

if ($key === '$permissions') {
if (empty($value)) {
$document->setAttribute('$permissions', []); // set default value
Expand Down Expand Up @@ -6356,7 +6362,6 @@ public function encode(Document $collection, Document $document): Document
if (!$array) {
$value = $value[0];
}

$document->setAttribute($key, $value);
}

Expand Down
12 changes: 12 additions & 0 deletions src/Database/Validator/PartialStructure.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,19 @@ public function isValid($document): bool
$name = $attribute['$id'] ?? '';
$keys[$name] = $attribute;
}
/**
* @var array<string, mixed> $requiredAttributes
*/
$requiredAttributes = [];
foreach ($this->attributes as $attribute) {
if ($attribute['required'] === true && $document->offsetExists($attribute['$id'])) {
$requiredAttributes[] = $attribute;
}
}

if (!$this->checkForAllRequiredValues($structure, $requiredAttributes, $keys)) {
return false;
}
if (!$this->checkForUnknownAttributes($structure, $keys)) {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Database/Validator/Structure.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class Structure extends Validator
'$id' => '$createdAt',
'type' => Database::VAR_DATETIME,
'size' => 0,
'required' => false,
'required' => true,
'signed' => false,
'array' => false,
'filters' => [],
Expand All @@ -80,7 +80,7 @@ class Structure extends Validator
'$id' => '$updatedAt',
'type' => Database::VAR_DATETIME,
'size' => 0,
'required' => false,
'required' => true,
'signed' => false,
'array' => false,
'filters' => [],
Expand Down
Loading