From 43b4f7aa63f5d979d7b46a373c81a29630bdfdc7 Mon Sep 17 00:00:00 2001 From: Prateek Banga Date: Fri, 21 Jul 2023 00:20:53 +0530 Subject: [PATCH] Add support for queries in List attributes endpoint --- app/controllers/api/databases.php | 50 ++++++++++++++++--- .../Database/Validator/Queries/Attributes.php | 23 +++++++++ .../e2e/Services/Databases/DatabasesBase.php | 18 ++++++- 3 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 29f9c6d0be..d5360a7865 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -48,6 +48,7 @@ use Appwrite\Utopia\Database\Validator\Queries\Collections; use Appwrite\Utopia\Database\Validator\Queries\Databases; use Appwrite\Utopia\Database\Validator\Queries\Document as DocumentValidator; use Appwrite\Utopia\Database\Validator\Queries\Documents; +use Appwrite\Utopia\Database\Validator\Queries\Attributes; use Utopia\Config\Config; use MaxMind\Db\Reader; use Utopia\Validator\Nullable; @@ -1657,9 +1658,10 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') ->label('sdk.response.model', Response::MODEL_ATTRIBUTE_LIST) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') + ->param('queries', [], new Attributes(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Collections::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') - ->action(function (string $databaseId, string $collectionId, Response $response, Database $dbForProject) { + ->action(function (string $databaseId, string $collectionId, array $queries, Response $response, Database $dbForProject) { $database = Authorization::skip(fn() => $dbForProject->getDocument('databases', $databaseId)); @@ -1673,12 +1675,48 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attributes = $collection->getAttribute('attributes'); + $queries = Query::parseQueries($queries); + \array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId])); - $response->dynamic(new Document([ - 'total' => \count($attributes), - 'attributes' => $attributes - ]), Response::MODEL_ATTRIBUTE_LIST); + if (!empty($search)) { + $queries[] = Query::search('search', $search); + } + + // Get cursor document if there was a cursor query + $cursor = Query::getByType($queries, Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE); + $cursor = reset($cursor); + + if ($cursor) { + $attributeId = $cursor->getValue(); + + $cursorDocument = Authorization::skip(fn() => $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $attributeId)); + + if ($cursorDocument->isEmpty()) { + throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Attribute '{$attributeId}' for the 'cursor' value not found."); + } + + $cursor->setValue($cursorDocument); + } + + $attributes = $dbForProject->find('attributes', $queries); + + //Add relationship data from options to attributes as it loses options during response setup + foreach ($attributes as $attribute) { + if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { + $options = $attribute->getAttribute('options'); + $attribute->setAttribute('relatedCollection', $options['relatedCollection']); + $attribute->setAttribute('relationType', $options['relationType']); + $attribute->setAttribute('twoWay', $options['twoWay']); + $attribute->setAttribute('twoWayKey', $options['twoWayKey']); + $attribute->setAttribute('side', $options['side']); + $attribute->setAttribute('onDelete', $options['onDelete']); + } + } + $filterQueries = Query::groupByType($queries)['filters']; + $response->dynamic(new Document([ + 'total' => $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT), + 'attributes' => $attributes, + ]), Response::MODEL_ATTRIBUTE_LIST); }); App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php new file mode 100644 index 0000000000..44135a3a79 --- /dev/null +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Attributes.php @@ -0,0 +1,23 @@ +client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ]), [ + 'queries' => ['equal("type", "string")'], + ]); + $this->assertEquals(200, $attributes['headers']['status-code']); + $this->assertEquals(3, $attributes['body']['total']); + } + /** * @depends testCreateAttributes */ @@ -679,7 +696,6 @@ trait DatabasesBase $this->assertEquals(10, $attributes['body']['total']); $attributes = $attributes['body']['attributes']; - $this->assertIsArray($attributes); $this->assertCount(10, $attributes);