1
0
Fork 0
mirror of synced 2024-09-29 08:51:28 +13:00

Add select queries support to list indexes and list attributes endpoint

This commit is contained in:
prateek banga 2023-08-03 17:34:28 +05:30
parent 27e0ec339a
commit 1d558fa5f5
6 changed files with 163 additions and 113 deletions

View file

@ -1676,54 +1676,77 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes')
throw new Exception(Exception::COLLECTION_NOT_FOUND);
}
$queries = Query::parseQueries($queries);
foreach ($queries as $query) {
$queriesFromRequest = Query::parseQueries($queries);
// Add type property in query if select query exists and type property doesn't exist as type is required for response model
$hasDetailsinQuery = [
'selectQuery' => false,
'typeAttributeInSelectQuery' => false,
];
foreach ($queriesFromRequest as $query) {
if ($query->getMethod() === Query::TYPE_SELECT) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, 'Select queries are not valid.');
$hasDetailsinQuery['selectQuery'] = true;
}
if(\array_search('type', $query->getValues())){
$hasDetailsinQuery['typeAttributeInSelectQuery'] = true;
}
}
\array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]));
$transformedQueries = $queriesFromRequest;
if ($hasDetailsinQuery['selectQuery'] && !$hasDetailsinQuery['typeAttributeInSelectQuery']) {
\array_push($transformedQueries, Query::select(['type']));
}
\array_push($transformedQueries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]));
// Get cursor document if there was a cursor query
$cursor = Query::getByType($queries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
$cursor = Query::getByType($transformedQueries, [Query::TYPE_CURSORAFTER, Query::TYPE_CURSORBEFORE]);
$cursor = reset($cursor);
if ($cursor) {
$attributeId = $cursor->getValue();
$cursorDocument = Authorization::skip(fn() => $dbForProject->find('attributes', [
Query::equal('collectionId', [$collectionId]),
Query::equal('databaseId', [$databaseId]),
Query::equal('key', [$attributeId]),
Query::limit(1),
]));
if (empty($cursorDocument) || $cursorDocument[0]->isEmpty()) {
throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Attribute '{$attributeId}' for the 'cursor' value not found.");
}
$cursor->setValue($cursorDocument[0]);
}
$attributes = $dbForProject->find('attributes', $queries);
$attributes = $dbForProject->find('attributes', $transformedQueries);
$filterQueries = Query::groupByType($transformedQueries)['filters'];
$total = $dbForProject->count('attributes', $filterQueries, APP_LIMIT_COUNT);
//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) {
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']);
if(!\is_null($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),
$output = $response->output(new Document([
'total' => $total,
'attributes' => $attributes,
]), Response::MODEL_ATTRIBUTE_LIST);
// If type Attribute didn't exist in select query we need to remove type attribute from attribute list
if ($hasDetailsinQuery['selectQuery'] && !$hasDetailsinQuery['typeAttributeInSelectQuery']) {
foreach($output['attributes'] as &$attribute) {
unset($attribute['type']);
}
}
$response->static($output);
});
App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key')
@ -2551,11 +2574,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes')
}
$queries = Query::parseQueries($queries);
foreach ($queries as $query) {
if ($query->getMethod() === Query::TYPE_SEARCH) {
throw new Exception(Exception::GENERAL_QUERY_INVALID, 'Select queries are not valid.');
}
}
\array_push($queries, Query::equal('collectionId', [$collectionId]), Query::equal('databaseId', [$databaseId]));
// Get cursor document if there was a cursor query

View file

@ -207,9 +207,11 @@ App::init()
$deletes->setProject($project);
$database->setProject($project);
$dbForProject->on(Database::EVENT_DOCUMENT_CREATE, fn ($event, Document $document) => $databaseListener($event, $document, $usage));
$calculateUsage = fn ($event, Document $document) => $databaseListener($event, $document, $usage);
$dbForProject->on(Database::EVENT_DOCUMENT_DELETE, fn ($event, Document $document) => $databaseListener($event, $document, $usage));
$dbForProject->on(Database::EVENT_DOCUMENT_CREATE, 'calculate-usage', $calculateUsage);
$dbForProject->on(Database::EVENT_DOCUMENT_DELETE, 'calculate-usage', $calculateUsage);
$useCache = $route->getLabel('cache', false);

View file

@ -43,13 +43,13 @@
"ext-sockets": "*",
"appwrite/php-clamav": "2.0.*",
"appwrite/php-runtimes": "0.11.*",
"utopia-php/abuse": "0.27.*",
"utopia-php/abuse": "0.29.*",
"utopia-php/analytics": "0.2.*",
"utopia-php/audit": "0.29.*",
"utopia-php/audit": "0.31.*",
"utopia-php/cache": "0.8.*",
"utopia-php/cli": "0.13.*",
"utopia-php/config": "0.2.*",
"utopia-php/database": "0.38.*",
"utopia-php/database": "0.40.*",
"utopia-php/domains": "1.1.*",
"utopia-php/framework": "0.28.*",
"utopia-php/image": "0.5.*",

101
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c41be9b81d4ee69cf915be4c7ba37975",
"content-hash": "1dde9b87dc894a8ab765cad3567bfe7c",
"packages": [
{
"name": "adhocore/jwt",
@ -994,16 +994,16 @@
},
{
"name": "matomo/device-detector",
"version": "6.1.3",
"version": "6.1.4",
"source": {
"type": "git",
"url": "https://github.com/matomo-org/device-detector.git",
"reference": "3e0fac7e77f3faadc3858fea9f5fa7efeb9cf239"
"reference": "74f6c4f6732b3ad6cdf25560746841d522969112"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/matomo-org/device-detector/zipball/3e0fac7e77f3faadc3858fea9f5fa7efeb9cf239",
"reference": "3e0fac7e77f3faadc3858fea9f5fa7efeb9cf239",
"url": "https://api.github.com/repos/matomo-org/device-detector/zipball/74f6c4f6732b3ad6cdf25560746841d522969112",
"reference": "74f6c4f6732b3ad6cdf25560746841d522969112",
"shasum": ""
},
"require": {
@ -1059,7 +1059,7 @@
"source": "https://github.com/matomo-org/matomo",
"wiki": "https://dev.matomo.org/"
},
"time": "2023-06-06T11:58:07+00:00"
"time": "2023-08-02T08:48:53+00:00"
},
{
"name": "mongodb/mongodb",
@ -1804,23 +1804,23 @@
},
{
"name": "utopia-php/abuse",
"version": "0.27.0",
"version": "0.29.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/abuse.git",
"reference": "d1115f5843e903ffaba9c23e450b33c0fe265ae0"
"reference": "7589d0c7a6f685fcbb02d57875f034bd233ec262"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/d1115f5843e903ffaba9c23e450b33c0fe265ae0",
"reference": "d1115f5843e903ffaba9c23e450b33c0fe265ae0",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/7589d0c7a6f685fcbb02d57875f034bd233ec262",
"reference": "7589d0c7a6f685fcbb02d57875f034bd233ec262",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-pdo": "*",
"php": ">=8.0",
"utopia-php/database": "0.38.*"
"utopia-php/database": "0.40.*"
},
"require-dev": {
"laravel/pint": "1.5.*",
@ -1847,9 +1847,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.27.0"
"source": "https://github.com/utopia-php/abuse/tree/0.29.0"
},
"time": "2023-07-15T00:53:50+00:00"
"time": "2023-08-03T08:22:12+00:00"
},
{
"name": "utopia-php/analytics",
@ -1908,21 +1908,21 @@
},
{
"name": "utopia-php/audit",
"version": "0.29.0",
"version": "0.31.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/audit.git",
"reference": "5318538f457bf73623629345c98ea06371ca5dd4"
"reference": "f1b0165fccb6ec665f7ae947bfed56a8f6b877cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/5318538f457bf73623629345c98ea06371ca5dd4",
"reference": "5318538f457bf73623629345c98ea06371ca5dd4",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/f1b0165fccb6ec665f7ae947bfed56a8f6b877cb",
"reference": "f1b0165fccb6ec665f7ae947bfed56a8f6b877cb",
"shasum": ""
},
"require": {
"php": ">=8.0",
"utopia-php/database": "0.38.*"
"utopia-php/database": "0.40.*"
},
"require-dev": {
"laravel/pint": "1.5.*",
@ -1949,9 +1949,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.29.0"
"source": "https://github.com/utopia-php/audit/tree/0.31.0"
},
"time": "2023-07-15T00:51:10+00:00"
"time": "2023-08-03T08:22:32+00:00"
},
{
"name": "utopia-php/cache",
@ -2108,16 +2108,16 @@
},
{
"name": "utopia-php/database",
"version": "0.38.0",
"version": "0.40.0",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/database.git",
"reference": "59e4684cf87e03c12dab9240158c1dfc6888e534"
"reference": "ec586ba1c5fc83856df4feaa05464da72b72ee0d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/59e4684cf87e03c12dab9240158c1dfc6888e534",
"reference": "59e4684cf87e03c12dab9240158c1dfc6888e534",
"url": "https://api.github.com/repos/utopia-php/database/zipball/ec586ba1c5fc83856df4feaa05464da72b72ee0d",
"reference": "ec586ba1c5fc83856df4feaa05464da72b72ee0d",
"shasum": ""
},
"require": {
@ -2158,9 +2158,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.38.0"
"source": "https://github.com/utopia-php/database/tree/0.40.0"
},
"time": "2023-07-14T07:49:38+00:00"
"time": "2023-08-03T08:01:37+00:00"
},
{
"name": "utopia-php/domains",
@ -3785,16 +3785,16 @@
},
{
"name": "phpstan/phpdoc-parser",
"version": "1.22.1",
"version": "1.23.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0"
"reference": "a2b24135c35852b348894320d47b3902a94bc494"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/65c39594fbd8c67abfc68bb323f86447bab79cc0",
"reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a2b24135c35852b348894320d47b3902a94bc494",
"reference": "a2b24135c35852b348894320d47b3902a94bc494",
"shasum": ""
},
"require": {
@ -3826,22 +3826,22 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.22.1"
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.23.0"
},
"time": "2023-06-29T20:46:06+00:00"
"time": "2023-07-23T22:17:56+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.26",
"version": "9.2.27",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1"
"reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1",
"reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1",
"reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1",
"shasum": ""
},
"require": {
@ -3897,7 +3897,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26"
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27"
},
"funding": [
{
@ -3905,7 +3906,7 @@
"type": "github"
}
],
"time": "2023-03-06T12:58:08+00:00"
"time": "2023-07-26T13:44:30+00:00"
},
{
"name": "phpunit/php-file-iterator",
@ -4757,16 +4758,16 @@
},
{
"name": "sebastian/global-state",
"version": "5.0.5",
"version": "5.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
"reference": "bde739e7565280bda77be70044ac1047bc007e34"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34",
"reference": "bde739e7565280bda77be70044ac1047bc007e34",
"shasum": ""
},
"require": {
@ -4809,7 +4810,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
"source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6"
},
"funding": [
{
@ -4817,7 +4818,7 @@
"type": "github"
}
],
"time": "2022-02-14T08:28:10+00:00"
"time": "2023-08-02T09:26:13+00:00"
},
{
"name": "sebastian/lines-of-code",
@ -5580,16 +5581,16 @@
},
{
"name": "twig/twig",
"version": "v3.6.1",
"version": "v3.7.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "7e7d5839d4bec168dfeef0ac66d5c5a2edbabffd"
"reference": "5cf942bbab3df42afa918caeba947f1b690af64b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/7e7d5839d4bec168dfeef0ac66d5c5a2edbabffd",
"reference": "7e7d5839d4bec168dfeef0ac66d5c5a2edbabffd",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/5cf942bbab3df42afa918caeba947f1b690af64b",
"reference": "5cf942bbab3df42afa918caeba947f1b690af64b",
"shasum": ""
},
"require": {
@ -5635,7 +5636,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.6.1"
"source": "https://github.com/twigphp/Twig/tree/v3.7.0"
},
"funding": [
{
@ -5647,7 +5648,7 @@
"type": "tidelift"
}
],
"time": "2023-06-08T12:52:13+00:00"
"time": "2023-07-26T07:16:09+00:00"
}
],
"aliases": [],

View file

@ -8,7 +8,8 @@ class Indexes extends Base
'key',
'type',
'status',
'error'
'attributes',
'error',
];
/**
@ -17,6 +18,6 @@ class Indexes extends Base
*/
public function __construct()
{
parent::__construct('attributes', self::ALLOWED_ATTRIBUTES);
parent::__construct('indexes', self::ALLOWED_ATTRIBUTES);
}
}

View file

@ -458,6 +458,33 @@ class Response extends SwooleResponse
}
}
/**
* Sends the response based on content type
*
* @param array $ouput
*
* return void
* @throws Exception
*/
public function static(array $output): void
{
switch ($this->getContentType()) {
case self::CONTENT_TYPE_JSON:
$this->json(!empty($output) ? $output : new \stdClass());
break;
case self::CONTENT_TYPE_YAML:
$this->yaml(!empty($output) ? $output : new \stdClass());
break;
case self::CONTENT_TYPE_NULL:
break;
default:
$this->json(!empty($output) ? $output : new \stdClass());
}
}
/**
* Generate valid response object from document data
*
@ -491,45 +518,46 @@ class Response extends SwooleResponse
}
}
if ($rule['array']) {
if (!is_array($document[$key])) {
throw new Exception($key . ' must be an array of type ' . $rule['type']);
}
foreach ($document[$key] as $index => $item) {
if ($item instanceof Document) {
if (\is_array($rule['type'])) {
foreach ($rule['type'] as $type) {
$condition = false;
foreach ($this->getModel($type)->conditions as $attribute => $val) {
$condition = $item->getAttribute($attribute) === $val;
if (!$condition) {
if ($rule['required'] && !(\is_null($document[$key]))) {
if ($rule['array']) {
if (!is_array($document[$key])) {
throw new Exception($key . ' must be an array of type ' . $rule['type']);
}
foreach ($document[$key] as $index => $item) {
if ($item instanceof Document) {
if (\is_array($rule['type'])) {
foreach ($rule['type'] as $type) {
$condition = false;
foreach ($this->getModel($type)->conditions as $attribute => $val) {
$condition = $item->getAttribute($attribute) === $val;
if (!$condition) {
break;
}
}
if ($condition) {
$ruleType = $type;
break;
}
}
if ($condition) {
$ruleType = $type;
break;
}
} else {
$ruleType = $rule['type'];
}
} else {
$ruleType = $rule['type'];
if (!array_key_exists($ruleType, $this->models)) {
throw new Exception('Missing model for rule: ' . $ruleType);
}
$data[$key][$index] = $this->output($item, $ruleType);
}
if (!array_key_exists($ruleType, $this->models)) {
throw new Exception('Missing model for rule: ' . $ruleType);
}
$data[$key][$index] = $this->output($item, $ruleType);
}
} else {
if ($document[$key] instanceof Document) {
$data[$key] = $this->output($data[$key], $rule['type']);
}
}
} else {
if ($document[$key] instanceof Document) {
$data[$key] = $this->output($data[$key], $rule['type']);
}
$output[$key] = $data[$key];
}
$output[$key] = $data[$key];
}
$this->payload = $output;