mirror of
https://github.com/appwrite/appwrite
synced 2026-05-23 08:58:35 +00:00
Merge pull request #10244 from appwrite/dat-588
Allow modifying createdAt and updatedAt with server side sdk and api key
This commit is contained in:
commit
e6f0804272
12 changed files with 2282 additions and 62 deletions
24
composer.lock
generated
24
composer.lock
generated
|
|
@ -69,16 +69,16 @@
|
|||
},
|
||||
{
|
||||
"name": "appwrite/appwrite",
|
||||
"version": "15.0.0",
|
||||
"version": "15.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-for-php.git",
|
||||
"reference": "deb97b62e0abed8a4fd5c5d48e77365cf89867cf"
|
||||
"reference": "c438b3885071ac7c0329199dce5e6f6a24dd215b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/deb97b62e0abed8a4fd5c5d48e77365cf89867cf",
|
||||
"reference": "deb97b62e0abed8a4fd5c5d48e77365cf89867cf",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-for-php/zipball/c438b3885071ac7c0329199dce5e6f6a24dd215b",
|
||||
"reference": "c438b3885071ac7c0329199dce5e6f6a24dd215b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -104,10 +104,10 @@
|
|||
"support": {
|
||||
"email": "team@appwrite.io",
|
||||
"issues": "https://github.com/appwrite/sdk-for-php/issues",
|
||||
"source": "https://github.com/appwrite/sdk-for-php/tree/15.0.0",
|
||||
"source": "https://github.com/appwrite/sdk-for-php/tree/15.1.0",
|
||||
"url": "https://appwrite.io/support"
|
||||
},
|
||||
"time": "2025-05-18T09:47:10+00:00"
|
||||
"time": "2025-08-01T04:50:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "appwrite/php-clamav",
|
||||
|
|
@ -4814,16 +4814,16 @@
|
|||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "0.41.26",
|
||||
"version": "0.41.27",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "5a13191a5a4bdec8fe1b1180ff67f75c4ff6ac0b"
|
||||
"reference": "083fd2e8163d6a4e59ee971ac6cb97277d831dd5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/5a13191a5a4bdec8fe1b1180ff67f75c4ff6ac0b",
|
||||
"reference": "5a13191a5a4bdec8fe1b1180ff67f75c4ff6ac0b",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/083fd2e8163d6a4e59ee971ac6cb97277d831dd5",
|
||||
"reference": "083fd2e8163d6a4e59ee971ac6cb97277d831dd5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -4859,9 +4859,9 @@
|
|||
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
|
||||
"support": {
|
||||
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.41.26"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/0.41.27"
|
||||
},
|
||||
"time": "2025-07-30T06:53:12+00:00"
|
||||
"time": "2025-07-31T10:20:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
|
|
|
|||
|
|
@ -125,16 +125,18 @@ class Update extends Action
|
|||
$documents = [];
|
||||
|
||||
try {
|
||||
$modified = $dbForProject->updateDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
new Document($data),
|
||||
$queries,
|
||||
onNext: function (Document $document) use ($plan, &$documents) {
|
||||
if (\count($documents) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) {
|
||||
$documents[] = $document;
|
||||
}
|
||||
},
|
||||
);
|
||||
$modified = $dbForProject->withPreserveDates(function () use ($plan, &$documents, $dbForProject, $database, $collection, $data, $queries) {
|
||||
return $dbForProject->updateDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
new Document($data),
|
||||
$queries,
|
||||
onNext: function (Document $document) use ($plan, &$documents) {
|
||||
if (\count($documents) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) {
|
||||
$documents[] = $document;
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
} catch (ConflictException) {
|
||||
throw new Exception($this->getConflictException());
|
||||
} catch (RelationshipException $e) {
|
||||
|
|
|
|||
|
|
@ -106,15 +106,17 @@ class Upsert extends Action
|
|||
$upserted = [];
|
||||
|
||||
try {
|
||||
$modified = $dbForProject->createOrUpdateDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
$documents,
|
||||
onNext: function (Document $document) use ($plan, &$upserted) {
|
||||
if (\count($upserted) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) {
|
||||
$upserted[] = $document;
|
||||
}
|
||||
},
|
||||
);
|
||||
$modified = $dbForProject->withPreserveDates(function () use ($dbForProject, $database, $collection, $documents, $plan, &$upserted) {
|
||||
return $dbForProject->createOrUpdateDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
$documents,
|
||||
onNext: function (Document $document) use ($plan, &$upserted) {
|
||||
if (\count($upserted) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) {
|
||||
$upserted[] = $document;
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
} catch (ConflictException) {
|
||||
throw new Exception($this->getConflictException());
|
||||
} catch (DuplicateException) {
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ class Create extends Action
|
|||
}
|
||||
};
|
||||
|
||||
$documents = \array_map(function ($document) use ($collection, $permissions, $checkPermissions, $isBulk, $documentId, $setPermissions) {
|
||||
$documents = \array_map(function ($document) use ($collection, $permissions, $checkPermissions, $isBulk, $documentId, $setPermissions, $isAPIKey, $isPrivilegedUser) {
|
||||
$document['$collection'] = $collection->getId();
|
||||
|
||||
// Determine the source ID depending on whether it's a bulk operation.
|
||||
|
|
@ -350,6 +350,18 @@ class Create extends Action
|
|||
|
||||
// Assign a unique ID if needed, otherwise use the provided ID.
|
||||
$document['$id'] = $sourceId === 'unique()' ? ID::unique() : $sourceId;
|
||||
|
||||
// Allowing to add createdAt and updatedAt timestamps if server side(api key
|
||||
if (!$isAPIKey && !$isPrivilegedUser) {
|
||||
if (isset($document['$createdAt'])) {
|
||||
throw new Exception($this->getInvalidStructureException(), 'Attribute "$createdAt" can not be modified. Please use a server SDK with an API key to modify server attributes.');
|
||||
}
|
||||
|
||||
if (isset($document['$updatedAt'])) {
|
||||
throw new Exception($this->getInvalidStructureException(), 'Attribute "$updatedAt" can not be modified. Please use a server SDK with an API key to modify server attributes.');
|
||||
}
|
||||
}
|
||||
|
||||
$document = new Document($document);
|
||||
$setPermissions($document, $permissions);
|
||||
$checkPermissions($collection, $document, Database::PERMISSION_CREATE);
|
||||
|
|
@ -358,9 +370,11 @@ class Create extends Action
|
|||
}, $documents);
|
||||
|
||||
try {
|
||||
$dbForProject->createDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
$documents
|
||||
$dbForProject->withPreserveDates(
|
||||
fn () => $dbForProject->createDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
$documents,
|
||||
)
|
||||
);
|
||||
} catch (DuplicateException) {
|
||||
throw new Exception($this->getDuplicateException());
|
||||
|
|
|
|||
|
|
@ -109,6 +109,16 @@ class Update extends Action
|
|||
throw new Exception($this->getParentNotFoundException());
|
||||
}
|
||||
|
||||
// Allowing to add createdAt and updatedAt timestamps if server side(api key)
|
||||
if (!$isAPIKey && !$isPrivilegedUser) {
|
||||
if (isset($data['$createdAt'])) {
|
||||
throw new Exception($this->getInvalidStructureException(), 'Attribute "$createdAt" can not be modified. Please use a server SDK with an API key to modify server attributes.');
|
||||
}
|
||||
|
||||
if (isset($data['$updatedAt'])) {
|
||||
throw new Exception($this->getInvalidStructureException(), 'Attribute "$updatedAt" can not be modified. Please use a server SDK with an API key to modify server attributes.');
|
||||
}
|
||||
}
|
||||
// Read permission should not be required for update
|
||||
/** @var Document $document */
|
||||
$document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId));
|
||||
|
|
@ -233,11 +243,11 @@ class Update extends Action
|
|||
try {
|
||||
$document = $dbForProject->withRequestTimestamp(
|
||||
$requestTimestamp,
|
||||
fn () => $dbForProject->updateDocument(
|
||||
fn () => $dbForProject->withPreserveDates(fn () => $dbForProject->updateDocument(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
$document->getId(),
|
||||
$newDocument
|
||||
)
|
||||
))
|
||||
);
|
||||
} catch (ConflictException) {
|
||||
throw new Exception($this->getConflictException());
|
||||
|
|
|
|||
|
|
@ -153,6 +153,16 @@ class Upsert extends Action
|
|||
}
|
||||
}
|
||||
}
|
||||
// Allowing to add createdAt and updatedAt timestamps if server side(api key)
|
||||
if (!$isAPIKey && !$isPrivilegedUser) {
|
||||
if (isset($data['$createdAt'])) {
|
||||
throw new Exception($this->getInvalidStructureException(), 'Attribute "$createdAt" can not be modified. Please use a server SDK with an API key to modify server attributes.');
|
||||
}
|
||||
|
||||
if (isset($data['$updatedAt'])) {
|
||||
throw new Exception($this->getInvalidStructureException(), 'Attribute "$updatedAt" can not be modified. Please use a server SDK with an API key to modify server attributes.');
|
||||
}
|
||||
}
|
||||
|
||||
$data['$id'] = $documentId;
|
||||
$data['$permissions'] = $permissions ?? [];
|
||||
|
|
@ -236,13 +246,15 @@ class Upsert extends Action
|
|||
|
||||
$upserted = [];
|
||||
try {
|
||||
$dbForProject->createOrUpdateDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
[$newDocument],
|
||||
onNext: function (Document $document) use (&$upserted) {
|
||||
$upserted[] = $document;
|
||||
},
|
||||
);
|
||||
$dbForProject->withPreserveDates(function () use (&$upserted, $dbForProject, $database, $collection, $newDocument) {
|
||||
return $dbForProject->createOrUpdateDocuments(
|
||||
'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(),
|
||||
[$newDocument],
|
||||
onNext: function (Document $document) use (&$upserted) {
|
||||
$upserted[] = $document;
|
||||
},
|
||||
);
|
||||
});
|
||||
} catch (ConflictException) {
|
||||
throw new Exception($this->getConflictException());
|
||||
} catch (DuplicateException) {
|
||||
|
|
|
|||
|
|
@ -2850,7 +2850,6 @@ trait DatabasesBase
|
|||
'releaseYear' => 2017,
|
||||
'birthDay' => '1976-06-12 14:12:55',
|
||||
'actors' => [],
|
||||
'$createdAt' => 5 // Should be ignored
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
|
|
@ -4215,17 +4214,19 @@ trait DatabasesBase
|
|||
$row = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/grids/tables/' . $data['moviesId'] . '/rows/' . $rowId, $headers, [
|
||||
'data' => [
|
||||
'title' => 'Again Updated Date Test',
|
||||
'$createdAt' => '2022-08-01 13:09:23.040', // $createdAt is not updatable
|
||||
'$updatedAt' => '2022-08-01 13:09:23.050' // system will update it not api
|
||||
'$createdAt' => '2022-08-01 13:09:23.040',
|
||||
'$updatedAt' => '2022-08-01 13:09:23.050'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals($row['body']['title'], 'Again Updated Date Test');
|
||||
$this->assertEquals($row['body']['$createdAt'], $createdAt);
|
||||
$this->assertNotEquals($row['body']['$createdAt'], '2022-08-01 13:09:23.040');
|
||||
$this->assertNotEquals($row['body']['$updatedAt'], $updatedAt);
|
||||
$this->assertNotEquals($row['body']['$updatedAt'], $updatedAtSecond);
|
||||
$this->assertNotEquals($row['body']['$updatedAt'], '2022-08-01 13:09:23.050');
|
||||
if ($this->getSide() === 'client') {
|
||||
$this->assertEquals($row['headers']['status-code'], 400);
|
||||
} else {
|
||||
$this->assertEquals($row['body']['title'], 'Again Updated Date Test');
|
||||
$this->assertEquals($row['body']['$createdAt'], DateTime::formatTz('2022-08-01 13:09:23.040'));
|
||||
$this->assertEquals($row['body']['$updatedAt'], DateTime::formatTz('2022-08-01 13:09:23.050'));
|
||||
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -890,4 +890,158 @@ class DatabasesCustomClientTest extends Scope
|
|||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
public function testModifyCreatedAtUpdatedAtSingleRow(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
$table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'tableId' => ID::unique(),
|
||||
'name' => 'Test Table',
|
||||
'rowSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
$tableId = $table['body']['$id'];
|
||||
|
||||
// Create string column
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/columns/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'title',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
// Test 1: Try to create row with $createdAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'title' => 'Test Movie',
|
||||
'$createdAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 2: Try to create row with $updatedAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'title' => 'Test Movie',
|
||||
'$updatedAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 3: Try to create row with both $createdAt and $updatedAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'title' => 'Test Movie',
|
||||
'$createdAt' => '2000-01-01T10:00:00.000+00:00',
|
||||
'$updatedAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 4: Create a valid row first
|
||||
$validRow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'rowId' => ID::unique(),
|
||||
'data' => [
|
||||
'title' => 'Valid Movie'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $validRow['headers']['status-code']);
|
||||
$rowId = $validRow['body']['$id'];
|
||||
|
||||
// Test 5: Try to update row with $createdAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $rowId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'title' => 'Updated Movie',
|
||||
'$createdAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 6: Try to update row with $updatedAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $rowId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'title' => 'Updated Movie',
|
||||
'$updatedAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 7: Try to update row with both $createdAt and $updatedAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $rowId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'title' => 'Updated Movie',
|
||||
'$createdAt' => '2000-01-01T10:00:00.000+00:00',
|
||||
'$updatedAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/grids/tables/' . $tableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5189,4 +5189,947 @@ class DatabasesCustomServerTest extends Scope
|
|||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
public function testDateTimeRow(): void
|
||||
{
|
||||
$databaseId = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'DateTime Test Database',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $databaseId['headers']['status-code']);
|
||||
$databaseId = $databaseId['body']['$id'];
|
||||
|
||||
$table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'tableId' => ID::unique(),
|
||||
'name' => 'create_modify_dates',
|
||||
'rowSecurity' => true,
|
||||
'permissions' => [],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $table['headers']['status-code']);
|
||||
$tableId = $table['body']['$id'];
|
||||
|
||||
// Create string column
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/columns/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'string',
|
||||
'size' => 128,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
// Create datetime column
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/columns/datetime', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'datetime',
|
||||
'required' => false,
|
||||
'format' => 'datetime',
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$date = '2000-01-01T10:00:00.000+00:00';
|
||||
|
||||
// Test - default behaviour of external datetime column not changed
|
||||
$row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'row1',
|
||||
'data' => [
|
||||
'datetime' => ''
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $row['headers']['status-code']);
|
||||
$this->assertNotEmpty($row['body']['datetime']);
|
||||
$this->assertNotEmpty($row['body']['$createdAt']);
|
||||
$this->assertNotEmpty($row['body']['$updatedAt']);
|
||||
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/row1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertNotEmpty($row['body']['datetime']);
|
||||
$this->assertNotEmpty($row['body']['$createdAt']);
|
||||
$this->assertNotEmpty($row['body']['$updatedAt']);
|
||||
|
||||
// Test - modifying $createdAt and $updatedAt
|
||||
$row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'row2',
|
||||
'data' => [
|
||||
'$createdAt' => $date
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $row['headers']['status-code']);
|
||||
$this->assertEquals($row['body']['$createdAt'], $date);
|
||||
$this->assertNotEmpty($row['body']['$updatedAt']);
|
||||
$this->assertNotEquals($row['body']['$updatedAt'], $date);
|
||||
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/row2', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertEquals($row['body']['$createdAt'], $date);
|
||||
$this->assertNotEmpty($row['body']['$updatedAt']);
|
||||
$this->assertNotEquals($row['body']['$updatedAt'], $date);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/grids/tables/' . $tableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testSingleRowDateOperations(): void
|
||||
{
|
||||
$databaseId = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Single Date Operations Database',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $databaseId['headers']['status-code']);
|
||||
$databaseId = $databaseId['body']['$id'];
|
||||
|
||||
$table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'tableId' => ID::unique(),
|
||||
'name' => 'normal_date_operations',
|
||||
'rowSecurity' => true,
|
||||
'permissions' => [],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $table['headers']['status-code']);
|
||||
$tableId = $table['body']['$id'];
|
||||
|
||||
// Create string column
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/columns/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'string',
|
||||
'size' => 128,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
$date1 = '2000-01-01T10:00:00.000+00:00';
|
||||
$date2 = '2000-02-01T15:30:00.000+00:00';
|
||||
$date3 = '2000-03-01T20:45:00.000+00:00';
|
||||
|
||||
// Test 1: Create with custom createdAt, then update with custom updatedAt
|
||||
$row = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'row1',
|
||||
'data' => [
|
||||
'string' => 'initial',
|
||||
'$createdAt' => $createDate
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $row['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $row['body']['$createdAt']);
|
||||
$this->assertNotEquals($createDate, $row['body']['$updatedAt']);
|
||||
|
||||
// Update with custom updatedAt
|
||||
$updatedRow = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/row1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'updated',
|
||||
'$updatedAt' => $updateDate
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedRow['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $updatedRow['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $updatedRow['body']['$updatedAt']);
|
||||
|
||||
// Test 2: Create with both custom dates
|
||||
$row2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'row2',
|
||||
'data' => [
|
||||
'string' => 'both_dates',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $row2['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $row2['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $row2['body']['$updatedAt']);
|
||||
|
||||
// Test 3: Create without dates, then update with custom dates
|
||||
$row3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'row3',
|
||||
'data' => [
|
||||
'string' => 'no_dates'
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $row3['headers']['status-code']);
|
||||
|
||||
$updatedRow3 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/row3', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'updated_no_dates',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedRow3['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $updatedRow3['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $updatedRow3['body']['$updatedAt']);
|
||||
|
||||
// Test 4: Update only createdAt
|
||||
$row4 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'row4',
|
||||
'data' => [
|
||||
'string' => 'initial'
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $row4['headers']['status-code']);
|
||||
$originalCreatedAt4 = $row4['body']['$createdAt'];
|
||||
$originalUpdatedAt4 = $row4['body']['$updatedAt'];
|
||||
|
||||
$updatedRow4 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/row4', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'updated',
|
||||
'$updatedAt' => null,
|
||||
'$createdAt' => null
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedRow4['headers']['status-code']);
|
||||
$this->assertEquals($originalCreatedAt4, $updatedRow4['body']['$createdAt']);
|
||||
$this->assertNotEquals($originalUpdatedAt4, $updatedRow4['body']['$updatedAt']);
|
||||
|
||||
// Test 5: Update only updatedAt
|
||||
$finalRow4 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/row4', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'final',
|
||||
'$updatedAt' => $updateDate,
|
||||
'$createdAt' => $createDate
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $finalRow4['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $finalRow4['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $finalRow4['body']['$updatedAt']);
|
||||
|
||||
// Test 6: Create with updatedAt, update with createdAt
|
||||
$row5 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'row5',
|
||||
'data' => [
|
||||
'string' => 'row5',
|
||||
'$updatedAt' => $date2
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $row5['headers']['status-code']);
|
||||
$this->assertNotEquals($date2, $row5['body']['$createdAt']);
|
||||
$this->assertEquals($date2, $row5['body']['$updatedAt']);
|
||||
|
||||
$updatedRow5 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/row5', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'row5_updated',
|
||||
'$createdAt' => $date1
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedRow5['headers']['status-code']);
|
||||
$this->assertEquals($date1, $updatedRow5['body']['$createdAt']);
|
||||
$this->assertNotEquals($date2, $updatedRow5['body']['$updatedAt']);
|
||||
|
||||
// Test 7: Create with both dates, update with different dates
|
||||
$row6 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'row6',
|
||||
'data' => [
|
||||
'string' => 'row6',
|
||||
'$createdAt' => $date1,
|
||||
'$updatedAt' => $date2
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $row6['headers']['status-code']);
|
||||
$this->assertEquals($date1, $row6['body']['$createdAt']);
|
||||
$this->assertEquals($date2, $row6['body']['$updatedAt']);
|
||||
|
||||
$updatedRow6 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/row6', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'row6_updated',
|
||||
'$createdAt' => $date3,
|
||||
'$updatedAt' => $date3
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedRow6['headers']['status-code']);
|
||||
$this->assertEquals($date3, $updatedRow6['body']['$createdAt']);
|
||||
$this->assertEquals($date3, $updatedRow6['body']['$updatedAt']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/grids/tables/' . $tableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testBulkRowDateOperations(): void
|
||||
{
|
||||
$databaseId = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Bulk Date Operations Database',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $databaseId['headers']['status-code']);
|
||||
$databaseId = $databaseId['body']['$id'];
|
||||
|
||||
$table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'tableId' => ID::unique(),
|
||||
'name' => 'bulk_date_operations',
|
||||
'rowSecurity' => true,
|
||||
'permissions' => [],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $table['headers']['status-code']);
|
||||
$tableId = $table['body']['$id'];
|
||||
|
||||
// Create string column
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/columns/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'string',
|
||||
'size' => 128,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
|
||||
// Test 1: Bulk create with different date configurations
|
||||
$rows = [
|
||||
[
|
||||
'$id' => 'row1',
|
||||
'string' => 'row1',
|
||||
'$createdAt' => $createDate,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
[
|
||||
'$id' => 'row2',
|
||||
'string' => 'row2',
|
||||
'$updatedAt' => $updateDate,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
[
|
||||
'$id' => 'row3',
|
||||
'string' => 'row3',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
[
|
||||
'$id' => 'row4',
|
||||
'string' => 'row4',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
[
|
||||
'$id' => 'row5',
|
||||
'string' => 'row5',
|
||||
'$createdAt' => null,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
[
|
||||
'$id' => 'row6',
|
||||
'string' => 'row6',
|
||||
'$updatedAt' => null,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
// Create all rows in one bulk operation
|
||||
$bulkCreateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rows' => $rows
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $bulkCreateResponse['headers']['status-code']);
|
||||
$this->assertCount(count($rows), $bulkCreateResponse['body']['rows']);
|
||||
|
||||
// Verify initial state
|
||||
foreach (['row1', 'row3'] as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $row['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['row2', 'row3'] as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertEquals($updateDate, $row['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['row4', 'row5', 'row6'] as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertNotEmpty($row['body']['$createdAt'], "createdAt missing for $id");
|
||||
$this->assertNotEmpty($row['body']['$updatedAt'], "updatedAt missing for $id");
|
||||
}
|
||||
|
||||
// Test 2: Bulk update with custom dates
|
||||
$updateData = [
|
||||
'data' => [
|
||||
'string' => 'updated',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
// Use bulk update instead of individual updates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), $updateData);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(6, $response['body']['rows']);
|
||||
|
||||
// Verify updated state
|
||||
foreach (['row1', 'row3'] as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $row['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
$this->assertEquals($updateDate, $row['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
$this->assertEquals('updated', $row['body']['string'], "string mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['row2', 'row4', 'row5', 'row6'] as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertEquals($updateDate, $row['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
$this->assertEquals('updated', $row['body']['string'], "string mismatch for $id");
|
||||
}
|
||||
|
||||
$newDate = '2000-03-01T20:45:00.000+00:00';
|
||||
$updateDataEnabled = [
|
||||
'data' => [
|
||||
'string' => 'enabled_update',
|
||||
'$createdAt' => $newDate,
|
||||
'$updatedAt' => $newDate
|
||||
],
|
||||
];
|
||||
|
||||
// Use bulk update instead of individual updates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), $updateDataEnabled);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(6, $response['body']['rows']);
|
||||
|
||||
// Verify final state
|
||||
foreach (['row1', 'row2', 'row3', 'row4', 'row5', 'row6'] as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertEquals($newDate, $row['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
$this->assertEquals($newDate, $row['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
$this->assertEquals('enabled_update', $row['body']['string'], "string mismatch for $id");
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/grids/tables/' . $tableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testUpsertRowDateOperations(): void
|
||||
{
|
||||
$databaseId = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Upsert Date Operations Database',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $databaseId['headers']['status-code']);
|
||||
$databaseId = $databaseId['body']['$id'];
|
||||
|
||||
$table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'tableId' => ID::unique(),
|
||||
'name' => 'upsert_date_operations',
|
||||
'rowSecurity' => true,
|
||||
'permissions' => [],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $table['headers']['status-code']);
|
||||
$tableId = $table['body']['$id'];
|
||||
|
||||
// Create string column
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/columns/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'string',
|
||||
'size' => 128,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
$date1 = '2000-01-01T10:00:00.000+00:00';
|
||||
$date2 = '2000-02-01T15:30:00.000+00:00';
|
||||
$date3 = '2000-03-01T20:45:00.000+00:00';
|
||||
|
||||
// Test 1: Upsert new row with custom createdAt
|
||||
$upsertRow1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'upsert1',
|
||||
'data' => [
|
||||
'string' => 'upsert1_initial',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
],
|
||||
'$createdAt' => $createDate
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $upsertRow1['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $upsertRow1['body']['$createdAt']);
|
||||
$this->assertNotEquals($createDate, $upsertRow1['body']['$updatedAt']);
|
||||
|
||||
// Test 2: Upsert existing row with custom updatedAt
|
||||
$updatedUpsertRow1 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/upsert1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'upsert1_updated',
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedUpsertRow1['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $updatedUpsertRow1['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $updatedUpsertRow1['body']['$updatedAt']);
|
||||
|
||||
// Test 3: Upsert new row with both custom dates
|
||||
$upsertRow2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rowId' => 'upsert2',
|
||||
'data' => [
|
||||
'string' => 'upsert2_both_dates',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
],
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $upsertRow2['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $upsertRow2['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $upsertRow2['body']['$updatedAt']);
|
||||
|
||||
// Test 4: Upsert existing row with different dates
|
||||
$updatedUpsertRow2 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/upsert2', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'upsert2_updated',
|
||||
'$createdAt' => $date3,
|
||||
'$updatedAt' => $date3,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedUpsertRow2['headers']['status-code']);
|
||||
$this->assertEquals($date3, $updatedUpsertRow2['body']['$createdAt']);
|
||||
$this->assertEquals($date3, $updatedUpsertRow2['body']['$updatedAt']);
|
||||
|
||||
// Test 5: Bulk upsert operations with custom dates
|
||||
$upsertRows = [
|
||||
[
|
||||
'$id' => 'bulk_upsert1',
|
||||
'string' => 'bulk_upsert1_initial',
|
||||
'$createdAt' => $createDate
|
||||
],
|
||||
[
|
||||
'$id' => 'bulk_upsert2',
|
||||
'string' => 'bulk_upsert2_initial',
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
[
|
||||
'$id' => 'bulk_upsert3',
|
||||
'string' => 'bulk_upsert3_initial',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
[
|
||||
'$id' => 'bulk_upsert4',
|
||||
'string' => 'bulk_upsert4_initial'
|
||||
]
|
||||
];
|
||||
|
||||
// Create rows using bulk upsert
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'rows' => $upsertRows
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(4, $response['body']['rows']);
|
||||
|
||||
// Test 7: Verify initial bulk upsert state
|
||||
foreach (['bulk_upsert1', 'bulk_upsert3'] as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $row['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['bulk_upsert2', 'bulk_upsert3'] as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertEquals($updateDate, $row['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['bulk_upsert4'] as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertNotEmpty($row['body']['$createdAt'], "createdAt missing for $id");
|
||||
$this->assertNotEmpty($row['body']['$updatedAt'], "updatedAt missing for $id");
|
||||
}
|
||||
|
||||
// Test 8: Bulk upsert update with custom dates
|
||||
$newDate = '2000-04-01T12:00:00.000+00:00';
|
||||
$updateUpsertData = [
|
||||
'data' => [
|
||||
'string' => 'bulk_upsert_updated',
|
||||
'$createdAt' => $newDate,
|
||||
'$updatedAt' => $newDate
|
||||
],
|
||||
'queries' => [Query::equal('$id', ['bulk_upsert1','bulk_upsert2','bulk_upsert3','bulk_upsert4'])->toString()]
|
||||
];
|
||||
|
||||
$upsertIds = ['bulk_upsert1', 'bulk_upsert2', 'bulk_upsert3', 'bulk_upsert4'];
|
||||
|
||||
// Use bulk update instead of individual updates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), $updateUpsertData);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(4, $response['body']['rows']);
|
||||
|
||||
// Verify updated state
|
||||
foreach ($upsertIds as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertEquals($newDate, $row['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
$this->assertEquals($newDate, $row['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
$this->assertEquals('bulk_upsert_updated', $row['body']['string'], "string mismatch for $id");
|
||||
}
|
||||
|
||||
// Test 9: checking by passing null to each
|
||||
$updateUpsertDataNull = [
|
||||
'data' => [
|
||||
'string' => 'bulk_upsert_null_test',
|
||||
'$createdAt' => null,
|
||||
'$updatedAt' => null
|
||||
],
|
||||
'queries' => [Query::equal('$id', ['bulk_upsert1','bulk_upsert2','bulk_upsert3','bulk_upsert4'])->toString()]
|
||||
];
|
||||
|
||||
// Use bulk update instead of individual updates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), $updateUpsertDataNull);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(4, $response['body']['rows']);
|
||||
|
||||
// Verify null handling
|
||||
foreach ($upsertIds as $id) {
|
||||
$row = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/grids/tables/' . $tableId . '/rows/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $row['headers']['status-code']);
|
||||
$this->assertNotEmpty($row['body']['$createdAt'], "createdAt missing for $id");
|
||||
$this->assertNotEmpty($row['body']['$updatedAt'], "updatedAt missing for $id");
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/grids/tables/' . $tableId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2877,7 +2877,6 @@ trait DatabasesBase
|
|||
'releaseYear' => 2017,
|
||||
'birthDay' => '1976-06-12 14:12:55',
|
||||
'actors' => [],
|
||||
'$createdAt' => 5 // Should be ignored
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
|
|
@ -4207,17 +4206,18 @@ trait DatabasesBase
|
|||
$document = $this->client->call(Client::METHOD_PATCH, '/databases/' . $data['databaseId'] . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, $headers, [
|
||||
'data' => [
|
||||
'title' => 'Again Updated Date Test',
|
||||
'$createdAt' => '2022-08-01 13:09:23.040', // $createdAt is not updatable
|
||||
'$updatedAt' => '2022-08-01 13:09:23.050' // system will update it not api
|
||||
'$createdAt' => '2022-08-01 13:09:23.040',
|
||||
'$updatedAt' => '2022-08-01 13:09:23.050'
|
||||
]
|
||||
]);
|
||||
if ($this->getSide() === 'client') {
|
||||
$this->assertEquals($document['headers']['status-code'], 400);
|
||||
} else {
|
||||
$this->assertEquals($document['body']['title'], 'Again Updated Date Test');
|
||||
$this->assertEquals($document['body']['$createdAt'], DateTime::formatTz('2022-08-01 13:09:23.040'));
|
||||
$this->assertEquals($document['body']['$updatedAt'], DateTime::formatTz('2022-08-01 13:09:23.050'));
|
||||
|
||||
$this->assertEquals($document['body']['title'], 'Again Updated Date Test');
|
||||
$this->assertEquals($document['body']['$createdAt'], $createdAt);
|
||||
$this->assertNotEquals($document['body']['$createdAt'], '2022-08-01 13:09:23.040');
|
||||
$this->assertNotEquals($document['body']['$updatedAt'], $updatedAt);
|
||||
$this->assertNotEquals($document['body']['$updatedAt'], $updatedAtSecond);
|
||||
$this->assertNotEquals($document['body']['$updatedAt'], '2022-08-01 13:09:23.050');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -889,4 +889,157 @@ class DatabasesCustomClientTest extends Scope
|
|||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
}
|
||||
public function testModifyCreatedAtUpdatedAtSingleDocument(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
$table = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Test Table',
|
||||
'documentsecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
$collectionId = $table['body']['$id'];
|
||||
|
||||
// Create string column
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'title',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
// Test 1: Try to create document with $createdAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'title' => 'Test Movie',
|
||||
'$createdAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 2: Try to create document with $updatedAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'title' => 'Test Movie',
|
||||
'$updatedAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 3: Try to create document with both $createdAt and $updatedAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'title' => 'Test Movie',
|
||||
'$createdAt' => '2000-01-01T10:00:00.000+00:00',
|
||||
'$updatedAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 4: Create a valid document first
|
||||
$validRow = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'title' => 'Valid Movie'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $validRow['headers']['status-code']);
|
||||
$documentId = $validRow['body']['$id'];
|
||||
|
||||
// Test 5: Try to update document with $createdAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'title' => 'Updated Movie',
|
||||
'$createdAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 6: Try to update document with $updatedAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'title' => 'Updated Movie',
|
||||
'$updatedAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Test 7: Try to update document with both $createdAt and $updatedAt - should return 400
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'title' => 'Updated Movie',
|
||||
'$createdAt' => '2000-01-01T10:00:00.000+00:00',
|
||||
'$updatedAt' => '2000-01-01T10:00:00.000+00:00'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5243,4 +5243,933 @@ class DatabasesCustomServerTest extends Scope
|
|||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
public function testDateTimeDocument(): void
|
||||
{
|
||||
$databaseId = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'DateTime Test Database',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $databaseId['headers']['status-code']);
|
||||
$databaseId = $databaseId['body']['$id'];
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'create_modify_dates',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $collection['headers']['status-code']);
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create string attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'string',
|
||||
'size' => 128,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
// Create datetime attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/datetime', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'datetime',
|
||||
'required' => false,
|
||||
'format' => 'datetime',
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$date = '2000-01-01T10:00:00.000+00:00';
|
||||
|
||||
// Test - default behaviour of external datetime attribute not changed
|
||||
$doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'doc1',
|
||||
'data' => [
|
||||
'datetime' => ''
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc['headers']['status-code']);
|
||||
$this->assertNotEmpty($doc['body']['datetime']);
|
||||
$this->assertNotEmpty($doc['body']['$createdAt']);
|
||||
$this->assertNotEmpty($doc['body']['$updatedAt']);
|
||||
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/doc1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertNotEmpty($doc['body']['datetime']);
|
||||
$this->assertNotEmpty($doc['body']['$createdAt']);
|
||||
$this->assertNotEmpty($doc['body']['$updatedAt']);
|
||||
|
||||
// Test - modifying $createdAt and $updatedAt
|
||||
$doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'doc2',
|
||||
'data' => [
|
||||
'$createdAt' => $date
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc['headers']['status-code']);
|
||||
$this->assertEquals($doc['body']['$createdAt'], $date);
|
||||
$this->assertNotEmpty($doc['body']['$updatedAt']);
|
||||
$this->assertNotEquals($doc['body']['$updatedAt'], $date);
|
||||
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/doc2', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertEquals($doc['body']['$createdAt'], $date);
|
||||
$this->assertNotEmpty($doc['body']['$updatedAt']);
|
||||
$this->assertNotEquals($doc['body']['$updatedAt'], $date);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testSingleDocumentDateOperations(): void
|
||||
{
|
||||
$databaseId = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Single Date Operations Database',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $databaseId['headers']['status-code']);
|
||||
$databaseId = $databaseId['body']['$id'];
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'normal_date_operations',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $collection['headers']['status-code']);
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create string attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'string',
|
||||
'size' => 128,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
$date1 = '2000-01-01T10:00:00.000+00:00';
|
||||
$date2 = '2000-02-01T15:30:00.000+00:00';
|
||||
$date3 = '2000-03-01T20:45:00.000+00:00';
|
||||
|
||||
// Test 1: Create with custom createdAt, then update with custom updatedAt
|
||||
$doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'doc1',
|
||||
'data' => [
|
||||
'string' => 'initial',
|
||||
'$createdAt' => $createDate
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $doc['body']['$createdAt']);
|
||||
$this->assertNotEquals($createDate, $doc['body']['$updatedAt']);
|
||||
|
||||
// Update with custom updatedAt
|
||||
$updatedDoc = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/doc1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'updated',
|
||||
'$updatedAt' => $updateDate
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedDoc['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $updatedDoc['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $updatedDoc['body']['$updatedAt']);
|
||||
|
||||
// Test 2: Create with both custom dates
|
||||
$doc2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'doc2',
|
||||
'data' => [
|
||||
'string' => 'both_dates',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc2['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $doc2['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $doc2['body']['$updatedAt']);
|
||||
|
||||
// Test 3: Create without dates, then update with custom dates
|
||||
$doc3 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'doc3',
|
||||
'data' => [
|
||||
'string' => 'no_dates'
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc3['headers']['status-code']);
|
||||
|
||||
$updatedDoc3 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/doc3', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'updated_no_dates',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedDoc3['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $updatedDoc3['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $updatedDoc3['body']['$updatedAt']);
|
||||
|
||||
// Test 4: Update only createdAt
|
||||
$doc4 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'doc4',
|
||||
'data' => [
|
||||
'string' => 'initial'
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc4['headers']['status-code']);
|
||||
$originalCreatedAt4 = $doc4['body']['$createdAt'];
|
||||
$originalUpdatedAt4 = $doc4['body']['$updatedAt'];
|
||||
|
||||
$updatedDoc4 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/doc4', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'updated',
|
||||
'$updatedAt' => null,
|
||||
'$createdAt' => null
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedDoc4['headers']['status-code']);
|
||||
$this->assertEquals($originalCreatedAt4, $updatedDoc4['body']['$createdAt']);
|
||||
$this->assertNotEquals($originalUpdatedAt4, $updatedDoc4['body']['$updatedAt']);
|
||||
|
||||
// Test 5: Update only updatedAt
|
||||
$finalDoc4 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/doc4', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'final',
|
||||
'$updatedAt' => $updateDate,
|
||||
'$createdAt' => $createDate
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $finalDoc4['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $finalDoc4['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $finalDoc4['body']['$updatedAt']);
|
||||
|
||||
// Test 6: Create with updatedAt, update with createdAt
|
||||
$doc5 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'doc5',
|
||||
'data' => [
|
||||
'string' => 'doc5',
|
||||
'$updatedAt' => $date2
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc5['headers']['status-code']);
|
||||
$this->assertNotEquals($date2, $doc5['body']['$createdAt']);
|
||||
$this->assertEquals($date2, $doc5['body']['$updatedAt']);
|
||||
|
||||
$updatedDoc5 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/doc5', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'doc5_updated',
|
||||
'$createdAt' => $date1
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedDoc5['headers']['status-code']);
|
||||
$this->assertEquals($date1, $updatedDoc5['body']['$createdAt']);
|
||||
$this->assertNotEquals($date2, $updatedDoc5['body']['$updatedAt']);
|
||||
|
||||
// Test 7: Create with both dates, update with different dates
|
||||
$doc6 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'doc6',
|
||||
'data' => [
|
||||
'string' => 'doc6',
|
||||
'$createdAt' => $date1,
|
||||
'$updatedAt' => $date2
|
||||
],
|
||||
'permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $doc6['headers']['status-code']);
|
||||
$this->assertEquals($date1, $doc6['body']['$createdAt']);
|
||||
$this->assertEquals($date2, $doc6['body']['$updatedAt']);
|
||||
|
||||
$updatedDoc6 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/doc6', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'doc6_updated',
|
||||
'$createdAt' => $date3,
|
||||
'$updatedAt' => $date3
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedDoc6['headers']['status-code']);
|
||||
$this->assertEquals($date3, $updatedDoc6['body']['$createdAt']);
|
||||
$this->assertEquals($date3, $updatedDoc6['body']['$updatedAt']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testBulkDocumentDateOperations(): void
|
||||
{
|
||||
$databaseId = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Bulk Date Operations Database',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $databaseId['headers']['status-code']);
|
||||
$databaseId = $databaseId['body']['$id'];
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'bulk_date_operations',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $collection['headers']['status-code']);
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create string attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'string',
|
||||
'size' => 128,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
|
||||
// Test 1: Bulk create with different date configurations
|
||||
$documents = [
|
||||
[
|
||||
'$id' => 'doc1',
|
||||
'string' => 'doc1',
|
||||
'$createdAt' => $createDate,
|
||||
'$permissions' => [ Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),]
|
||||
],
|
||||
[
|
||||
'$id' => 'doc2',
|
||||
'string' => 'doc2',
|
||||
'$updatedAt' => $updateDate,
|
||||
'$permissions' => [ Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),]
|
||||
],
|
||||
[
|
||||
'$id' => 'doc3',
|
||||
'string' => 'doc3',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate,
|
||||
'$permissions' => [ Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),]
|
||||
],
|
||||
[
|
||||
'$id' => 'doc4',
|
||||
'string' => 'doc4',
|
||||
'$permissions' => [ Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),]
|
||||
],
|
||||
[
|
||||
'$id' => 'doc5',
|
||||
'string' => 'doc5',
|
||||
'$createdAt' => null,
|
||||
'$permissions' => [ Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),]
|
||||
],
|
||||
[
|
||||
'$id' => 'doc6',
|
||||
'string' => 'doc6',
|
||||
'$updatedAt' => null,
|
||||
'$permissions' => [ Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),]
|
||||
]
|
||||
];
|
||||
|
||||
// Create all documents in one bulk operation
|
||||
$bulkCreateResponse = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documents' => $documents
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $bulkCreateResponse['headers']['status-code']);
|
||||
$this->assertCount(count($documents), $bulkCreateResponse['body']['documents']);
|
||||
|
||||
// Verify initial state
|
||||
foreach (['doc1', 'doc3'] as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $doc['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['doc2', 'doc3'] as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertEquals($updateDate, $doc['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['doc4', 'doc5', 'doc6'] as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertNotEmpty($doc['body']['$createdAt'], "createdAt missing for $id");
|
||||
$this->assertNotEmpty($doc['body']['$updatedAt'], "updatedAt missing for $id");
|
||||
}
|
||||
|
||||
// Test 2: Bulk update with custom dates
|
||||
$updateData = [
|
||||
'data' => [
|
||||
'string' => 'updated',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate,
|
||||
'$permissions' => [ Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),]
|
||||
],
|
||||
];
|
||||
|
||||
// Use bulk update instead of individual updates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), $updateData);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(6, $response['body']['documents']);
|
||||
|
||||
// Verify updated state
|
||||
foreach (['doc1', 'doc3'] as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $doc['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
$this->assertEquals($updateDate, $doc['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
$this->assertEquals('updated', $doc['body']['string'], "string mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['doc2', 'doc4', 'doc5', 'doc6'] as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertEquals($updateDate, $doc['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
$this->assertEquals('updated', $doc['body']['string'], "string mismatch for $id");
|
||||
}
|
||||
|
||||
$newDate = '2000-03-01T20:45:00.000+00:00';
|
||||
$updateDataEnabled = [
|
||||
'data' => [
|
||||
'string' => 'enabled_update',
|
||||
'$createdAt' => $newDate,
|
||||
'$updatedAt' => $newDate
|
||||
],
|
||||
];
|
||||
|
||||
// Use bulk update instead of individual updates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), $updateDataEnabled);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(6, $response['body']['documents']);
|
||||
|
||||
// Verify final state
|
||||
foreach (['doc1', 'doc2', 'doc3', 'doc4', 'doc5', 'doc6'] as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertEquals($newDate, $doc['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
$this->assertEquals($newDate, $doc['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
$this->assertEquals('enabled_update', $doc['body']['string'], "string mismatch for $id");
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testUpsertDateOperations(): void
|
||||
{
|
||||
$databaseId = $this->client->call(Client::METHOD_POST, '/databases', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Upsert Date Operations Database',
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $databaseId['headers']['status-code']);
|
||||
$databaseId = $databaseId['body']['$id'];
|
||||
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'upsert_date_operations',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $collection['headers']['status-code']);
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create string attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'string',
|
||||
'size' => 128,
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
sleep(1);
|
||||
|
||||
$createDate = '2000-01-01T10:00:00.000+00:00';
|
||||
$updateDate = '2000-02-01T15:30:00.000+00:00';
|
||||
$date1 = '2000-01-01T10:00:00.000+00:00';
|
||||
$date2 = '2000-02-01T15:30:00.000+00:00';
|
||||
$date3 = '2000-03-01T20:45:00.000+00:00';
|
||||
|
||||
// Test 1: Upsert new document with custom createdAt
|
||||
$upsertDoc1 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'upsert1',
|
||||
'data' => [
|
||||
'string' => 'upsert1_initial',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
],
|
||||
'$createdAt' => $createDate
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $upsertDoc1['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $upsertDoc1['body']['$createdAt']);
|
||||
$this->assertNotEquals($createDate, $upsertDoc1['body']['$updatedAt']);
|
||||
|
||||
// Test 2: Upsert existing document with custom updatedAt
|
||||
$updatedUpsertDoc1 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/upsert1', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'upsert1_updated',
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedUpsertDoc1['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $updatedUpsertDoc1['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $updatedUpsertDoc1['body']['$updatedAt']);
|
||||
|
||||
// Test 3: Upsert new document with both custom dates
|
||||
$upsertDoc2 = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documentId' => 'upsert2',
|
||||
'data' => [
|
||||
'string' => 'upsert2_both_dates',
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
],
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $upsertDoc2['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $upsertDoc2['body']['$createdAt']);
|
||||
$this->assertEquals($updateDate, $upsertDoc2['body']['$updatedAt']);
|
||||
|
||||
// Test 4: Upsert existing document with different dates
|
||||
$updatedUpsertDoc2 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/upsert2', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'data' => [
|
||||
'string' => 'upsert2_updated',
|
||||
'$createdAt' => $date3,
|
||||
'$updatedAt' => $date3,
|
||||
'$permissions' => [
|
||||
Permission::read(Role::any()),
|
||||
Permission::write(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $updatedUpsertDoc2['headers']['status-code']);
|
||||
$this->assertEquals($date3, $updatedUpsertDoc2['body']['$createdAt']);
|
||||
$this->assertEquals($date3, $updatedUpsertDoc2['body']['$updatedAt']);
|
||||
|
||||
// Test 5: Bulk upsert operations with custom dates
|
||||
$upsertDocuments = [
|
||||
[
|
||||
'$id' => 'bulk_upsert1',
|
||||
'string' => 'bulk_upsert1_initial',
|
||||
'$createdAt' => $createDate
|
||||
],
|
||||
[
|
||||
'$id' => 'bulk_upsert2',
|
||||
'string' => 'bulk_upsert2_initial',
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
[
|
||||
'$id' => 'bulk_upsert3',
|
||||
'string' => 'bulk_upsert3_initial',
|
||||
'$createdAt' => $createDate,
|
||||
'$updatedAt' => $updateDate
|
||||
],
|
||||
[
|
||||
'$id' => 'bulk_upsert4',
|
||||
'string' => 'bulk_upsert4_initial'
|
||||
]
|
||||
];
|
||||
|
||||
// Create documents using bulk upsert
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'documents' => $upsertDocuments
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(4, $response['body']['documents']);
|
||||
|
||||
// Test 7: Verify initial bulk upsert state
|
||||
foreach (['bulk_upsert1', 'bulk_upsert3'] as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertEquals($createDate, $doc['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['bulk_upsert2', 'bulk_upsert3'] as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertEquals($updateDate, $doc['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
}
|
||||
|
||||
foreach (['bulk_upsert4'] as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertNotEmpty($doc['body']['$createdAt'], "createdAt missing for $id");
|
||||
$this->assertNotEmpty($doc['body']['$updatedAt'], "updatedAt missing for $id");
|
||||
}
|
||||
|
||||
// Test 8: Bulk upsert update with custom dates
|
||||
$newDate = '2000-04-01T12:00:00.000+00:00';
|
||||
$updateUpsertData = [
|
||||
'data' => [
|
||||
'string' => 'bulk_upsert_updated',
|
||||
'$createdAt' => $newDate,
|
||||
'$updatedAt' => $newDate
|
||||
],
|
||||
'queries' => [Query::equal('$id', ['bulk_upsert1','bulk_upsert2','bulk_upsert3','bulk_upsert4'])->toString()]
|
||||
];
|
||||
|
||||
$upsertIds = ['bulk_upsert1', 'bulk_upsert2', 'bulk_upsert3', 'bulk_upsert4'];
|
||||
|
||||
// Use bulk update instead of individual updates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), $updateUpsertData);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(4, $response['body']['documents']);
|
||||
|
||||
// Verify updated state
|
||||
foreach ($upsertIds as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertEquals($newDate, $doc['body']['$createdAt'], "createdAt mismatch for $id");
|
||||
$this->assertEquals($newDate, $doc['body']['$updatedAt'], "updatedAt mismatch for $id");
|
||||
$this->assertEquals('bulk_upsert_updated', $doc['body']['string'], "string mismatch for $id");
|
||||
}
|
||||
|
||||
// Test 9: checking by passing null to each
|
||||
$updateUpsertDataNull = [
|
||||
'data' => [
|
||||
'string' => 'bulk_upsert_null_test',
|
||||
'$createdAt' => null,
|
||||
'$updatedAt' => null
|
||||
],
|
||||
'queries' => [Query::equal('$id', ['bulk_upsert1','bulk_upsert2','bulk_upsert3','bulk_upsert4'])->toString()]
|
||||
];
|
||||
|
||||
// Use bulk update instead of individual updates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), $updateUpsertDataNull);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(4, $response['body']['documents']);
|
||||
|
||||
// Verify null handling
|
||||
foreach ($upsertIds as $id) {
|
||||
$doc = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $id, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $doc['headers']['status-code']);
|
||||
$this->assertNotEmpty($doc['body']['$createdAt'], "createdAt missing for $id");
|
||||
$this->assertNotEmpty($doc['body']['$updatedAt'], "updatedAt missing for $id");
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue