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
49 changes: 28 additions & 21 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; // Make sure user doesn't switch createdAt
Comment thread
ArnabChatterjee20k marked this conversation as resolved.
Outdated

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,29 +4366,31 @@ public function updateDocuments(
if (!empty($cursor) && $cursor->getCollection() !== $collection->getId()) {
throw new DatabaseException("Cursor document must be from the same Collection.");
}

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

if (($updates->getCreatedAt() === null || !$this->preserveDates)) {
unset($updates['$createdAt']);
} else {
$updates['$createdAt'] = $updates->getCreatedAt();
$attributesToCheckForRequiredValidation[] = '$createdAt';
}
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,
$this->adapter->getMinDateTime(),
$this->adapter->getMaxDateTime(),
);

if (!$validator->isValid($updates)) {
if (!$validator->isValid($updates, $attributesToCheckForRequiredValidation)) {
throw new StructureException($validator->getDescription());
}

Expand Down Expand Up @@ -4990,14 +4993,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 +6315,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 +6327,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)) {
Comment thread
abnegate marked this conversation as resolved.
$document->setAttribute($key, null);
continue;
}

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

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

Expand Down
15 changes: 14 additions & 1 deletion src/Database/Validator/PartialStructure.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ class PartialStructure extends Structure
* Returns true if valid or false if not.
*
* @param mixed $document
* @param array<int, string> $requiredAttributes optional list of required attributes to check
*
* @return bool
*/
public function isValid($document): bool
public function isValid($document, array $requiredAttributes = []): bool
{
if (!$document instanceof Document) {
$this->message = 'Value must be an instance of Document';
Expand All @@ -36,7 +37,19 @@ public function isValid($document): bool
$name = $attribute['$id'] ?? '';
$keys[$name] = $attribute;
}
/**
* @var array<mixed,mixed> $requiredAttributesMap
*/
$requiredAttributesMap = [];
foreach ($this->attributes as $attribute) {
if ($attribute['required'] === true && in_array($attribute['$id'], $requiredAttributes)) {
$requiredAttributesMap[] = $attribute;
}
}
Comment thread
ArnabChatterjee20k marked this conversation as resolved.

if (!$this->checkForAllRequiredValues($structure, $requiredAttributesMap, $keys)) {
return false;
}
Comment thread
ArnabChatterjee20k marked this conversation as resolved.
Outdated
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
Loading