1
0
Fork 0
mirror of synced 2024-06-01 18:39:57 +12:00

Merge branch 'feat-database-indexing' of https://github.com/appwrite/appwrite into sync-realtime-with-db-refactor

This commit is contained in:
Torsten Dittmann 2021-10-08 12:59:03 +02:00
commit 9aaf6c27e5
8 changed files with 344 additions and 82 deletions

View file

@ -214,7 +214,7 @@ $collections = [
'required' => false,
'default' => new stdClass,
'array' => false,
'filters' => ['json', 'range'],
'filters' => ['json', 'range', 'enum'],
],
[
'$id' => 'filters',

View file

@ -749,6 +749,61 @@ App::post('/v1/database/collections/:collectionId/attributes/email')
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE_EMAIL);
});
App::post('/v1/database/collections/:collectionId/attributes/enum')
->desc('Create Enum Attribute')
->groups(['api', 'database'])
->label('event', 'database.attributes.create')
->label('scope', 'collections.write')
->label('sdk.namespace', 'database')
->label('sdk.auth', [APP_AUTH_TYPE_KEY])
->label('sdk.method', 'createEnumAttribute')
->label('sdk.description', '/docs/references/database/create-attribute-enum.md')
->label('sdk.response.code', Response::STATUS_CODE_CREATED)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->label('sdk.response.model', Response::MODEL_ATTRIBUTE_ENUM)
->param('collectionId', '', new UID(), 'Collection unique ID. You can create a new collection using the Database service [server integration](/docs/server/database#createCollection).')
->param('attributeId', '', new Key(), 'Attribute ID.')
->param('elements', [], new ArrayList(new Text(0)), 'Array of elements in enumerated type. Uses length of longest element to determine size.')
->param('required', null, new Boolean(), 'Is attribute required?')
->param('default', null, new Text(0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true)
->param('array', false, new Boolean(), 'Is attribute an array?', true)
->inject('response')
->inject('dbForInternal')
->inject('database')
->inject('audits')
->inject('usage')
->action(function ($collectionId, $attributeId, $elements, $required, $default, $array, $response, $dbForInternal, $database, $audits, $usage) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal*/
/** @var Appwrite\Event\Event $database */
/** @var Appwrite\Event\Event $audits */
/** @var Appwrite\Stats\Stats $usage */
// use length of longest string as attribute size
$size = 0;
foreach ($elements as $element) {
$length = \strlen($element);
if ($length === 0) {
throw new Exception('Each enum element must not be empty', 400);
}
$size = ($length > $size) ? $length : $size;
}
$attribute = createAttribute($collectionId, new Document([
'$id' => $attributeId,
'type' => Database::VAR_STRING,
'size' => $size,
'required' => $required,
'default' => $default,
'array' => $array,
'format' => APP_DATABASE_ATTRIBUTE_ENUM,
'formatOptions' => ['elements' => $elements],
]), $response, $dbForInternal, $database, $audits, $usage);
$response->dynamic($attribute, Response::MODEL_ATTRIBUTE_ENUM);
});
App::post('/v1/database/collections/:collectionId/attributes/ip')
->desc('Create IP Address Attribute')
->groups(['api', 'database'])
@ -1052,6 +1107,7 @@ App::get('/v1/database/collections/:collectionId/attributes/:attributeId')
Response::MODEL_ATTRIBUTE_INTEGER,
Response::MODEL_ATTRIBUTE_FLOAT,
Response::MODEL_ATTRIBUTE_EMAIL,
Response::MODEL_ATTRIBUTE_ENUM,
Response::MODEL_ATTRIBUTE_URL,
Response::MODEL_ATTRIBUTE_IP,
Response::MODEL_ATTRIBUTE_STRING,])// needs to be last, since its condition would dominate any other string attribute
@ -1086,6 +1142,7 @@ App::get('/v1/database/collections/:collectionId/attributes/:attributeId')
Database::VAR_FLOAT => Response::MODEL_ATTRIBUTE_FLOAT,
Database::VAR_STRING => match($format) {
APP_DATABASE_ATTRIBUTE_EMAIL => Response::MODEL_ATTRIBUTE_EMAIL,
APP_DATABASE_ATTRIBUTE_ENUM => Response::MODEL_ATTRIBUTE_ENUM,
APP_DATABASE_ATTRIBUTE_IP => Response::MODEL_ATTRIBUTE_IP,
APP_DATABASE_ATTRIBUTE_URL => Response::MODEL_ATTRIBUTE_URL,
default => Response::MODEL_ATTRIBUTE_STRING,
@ -1559,6 +1616,7 @@ App::get('/v1/database/collections/:collectionId/documents')
throw new Exception($validator->getDescription(), 400);
}
$cursorDocument = null;
if (!empty($cursor)) {
$cursorDocument = $dbForExternal->getDocument($collectionId, $cursor);

View file

@ -45,6 +45,7 @@ use Utopia\Database\Database;
use Utopia\Database\Validator\Structure;
use Utopia\Database\Validator\Authorization;
use Utopia\Validator\Range;
use Utopia\Validator\WhiteList;
use Swoole\Database\PDOConfig;
use Swoole\Database\PDOPool;
use Swoole\Database\RedisConfig;
@ -64,6 +65,7 @@ const APP_LIMIT_USERS = 10000;
const APP_CACHE_BUSTER = 160;
const APP_VERSION_STABLE = '0.11.0';
const APP_DATABASE_ATTRIBUTE_EMAIL = 'email';
const APP_DATABASE_ATTRIBUTE_ENUM = 'enum';
const APP_DATABASE_ATTRIBUTE_IP = 'ip';
const APP_DATABASE_ATTRIBUTE_URL = 'url';
const APP_DATABASE_ATTRIBUTE_INT_RANGE = 'intRange';
@ -200,6 +202,22 @@ Database::addFilter('casting',
}
);
Database::addFilter('enum',
function($value, Document $attribute) {
if ($attribute->isSet('elements')) {
$attribute->removeAttribute('elements');
}
return $value;
},
function($value, Document $attribute) {
$formatOptions = json_decode($attribute->getAttribute('formatOptions', []), true);
if (isset($formatOptions['elements'])) {
$attribute->setAttribute('elements', $formatOptions['elements']);
}
return $value;
}
);
Database::addFilter('range',
function($value, Document $attribute) {
if ($attribute->isSet('min')) {
@ -322,6 +340,11 @@ Structure::addFormat(APP_DATABASE_ATTRIBUTE_EMAIL, function() {
return new Email();
}, Database::VAR_STRING);
Structure::addFormat(APP_DATABASE_ATTRIBUTE_ENUM, function($attribute) {
$elements = $attribute['formatOptions']['elements'];
return new WhiteList($elements);
}, Database::VAR_STRING);
Structure::addFormat(APP_DATABASE_ATTRIBUTE_IP, function() {
return new IP();
}, Database::VAR_STRING);

View file

@ -17,6 +17,7 @@ use Appwrite\Utopia\Response\Model\AttributeInteger;
use Appwrite\Utopia\Response\Model\AttributeFloat;
use Appwrite\Utopia\Response\Model\AttributeBoolean;
use Appwrite\Utopia\Response\Model\AttributeEmail;
use Appwrite\Utopia\Response\Model\AttributeEnum;
use Appwrite\Utopia\Response\Model\AttributeIP;
use Appwrite\Utopia\Response\Model\AttributeURL;
use Appwrite\Utopia\Response\Model\BaseList;
@ -95,11 +96,12 @@ class Response extends SwooleResponse
const MODEL_ATTRIBUTE = 'attribute';
const MODEL_ATTRIBUTE_LIST = 'attributeList';
const MODEL_ATTRIBUTE_STRING = 'attributeString';
const MODEL_ATTRIBUTE_INTEGER= 'attributeInteger';
const MODEL_ATTRIBUTE_FLOAT= 'attributeFloat';
const MODEL_ATTRIBUTE_BOOLEAN= 'attributeBoolean';
const MODEL_ATTRIBUTE_EMAIL= 'attributeEmail';
const MODEL_ATTRIBUTE_IP= 'attributeIp';
const MODEL_ATTRIBUTE_INTEGER = 'attributeInteger';
const MODEL_ATTRIBUTE_FLOAT = 'attributeFloat';
const MODEL_ATTRIBUTE_BOOLEAN = 'attributeBoolean';
const MODEL_ATTRIBUTE_EMAIL = 'attributeEmail';
const MODEL_ATTRIBUTE_ENUM = 'attributeEnum';
const MODEL_ATTRIBUTE_IP = 'attributeIp';
const MODEL_ATTRIBUTE_URL= 'attributeUrl';
// Users
@ -219,6 +221,7 @@ class Response extends SwooleResponse
->setModel(new AttributeFloat())
->setModel(new AttributeBoolean())
->setModel(new AttributeEmail())
->setModel(new AttributeEnum())
->setModel(new AttributeIP())
->setModel(new AttributeURL())
->setModel(new Index())

View file

@ -0,0 +1,66 @@
<?php
namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model\Attribute;
class AttributeEnum extends Attribute
{
public function __construct()
{
parent::__construct();
$this
->addRule('elements', [
'type' => self::TYPE_STRING,
'description' => 'Array of elements in enumerated type.',
'default' => null,
'example' => 'element',
'array' => true,
'require' => true,
])
->addRule('format', [
'type' => self::TYPE_STRING,
'description' => 'String format.',
'default' => APP_DATABASE_ATTRIBUTE_ENUM,
'example' => APP_DATABASE_ATTRIBUTE_ENUM,
'array' => false,
'require' => true,
])
->addRule('default', [
'type' => self::TYPE_STRING,
'description' => 'Default value for attribute when not provided. Cannot be set when attribute is required.',
'default' => null,
'example' => 'element',
'array' => false,
'require' => false,
])
;
}
public array $conditions = [
'type' => self::TYPE_STRING,
'format' => \APP_DATABASE_ATTRIBUTE_ENUM
];
/**
* Get Name
*
* @return string
*/
public function getName():string
{
return 'AttributeEnum';
}
/**
* Get Type
*
* @return string
*/
public function getType():string
{
return Response::MODEL_ATTRIBUTE_ENUM;
}
}

View file

@ -23,6 +23,7 @@ class AttributeList extends Model
Response::MODEL_ATTRIBUTE_INTEGER,
Response::MODEL_ATTRIBUTE_FLOAT,
Response::MODEL_ATTRIBUTE_EMAIL,
Response::MODEL_ATTRIBUTE_ENUM,
Response::MODEL_ATTRIBUTE_URL,
Response::MODEL_ATTRIBUTE_IP,
Response::MODEL_ATTRIBUTE_STRING // needs to be last, since its condition would dominate any other string attribute

View file

@ -48,6 +48,7 @@ class Collection extends Model
Response::MODEL_ATTRIBUTE_INTEGER,
Response::MODEL_ATTRIBUTE_FLOAT,
Response::MODEL_ATTRIBUTE_EMAIL,
Response::MODEL_ATTRIBUTE_ENUM,
Response::MODEL_ATTRIBUTE_URL,
Response::MODEL_ATTRIBUTE_IP,
Response::MODEL_ATTRIBUTE_STRING, // needs to be last, since its condition would dominate any other string attribute

View file

@ -144,6 +144,17 @@ trait DatabaseBase
'default' => 'default@example.com',
]);
$enum = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/attributes/enum', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'attributeId' => 'enum',
'elements' => ['yes', 'no', 'maybe'],
'required' => false,
'default' => 'maybe',
]);
$ip = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/attributes/ip', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -216,6 +227,17 @@ trait DatabaseBase
$this->assertEquals('email', $email['body']['format']);
$this->assertEquals('default@example.com', $email['body']['default']);
$this->assertEquals(201, $enum['headers']['status-code']);
$this->assertEquals('enum', $enum['body']['key']);
$this->assertEquals('string', $enum['body']['type']);
$this->assertEquals('processing', $enum['body']['status']);
$this->assertEquals(false, $enum['body']['required']);
$this->assertEquals(false, $enum['body']['array']);
$this->assertEquals('enum', $enum['body']['format']);
$this->assertEquals('maybe', $enum['body']['default']);
$this->assertIsArray($enum['body']['elements']);
$this->assertEquals(['yes', 'no', 'maybe'], $enum['body']['elements']);
$this->assertEquals(201, $ip['headers']['status-code']);
$this->assertEquals('ip', $ip['body']['key']);
$this->assertEquals('string', $ip['body']['type']);
@ -277,6 +299,12 @@ trait DatabaseBase
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$enumResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$enum['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]));
$ipResponse = $this->client->call(Client::METHOD_GET, "/database/collections/{$collectionId}/attributes/{$collectionId}_{$ip['body']['key']}",array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -325,6 +353,16 @@ trait DatabaseBase
$this->assertEquals($email['body']['format'], $emailResponse['body']['format']);
$this->assertEquals($email['body']['default'], $emailResponse['body']['default']);
$this->assertEquals(200, $enumResponse['headers']['status-code']);
$this->assertEquals($enum['body']['key'], $enumResponse['body']['key']);
$this->assertEquals($enum['body']['type'], $enumResponse['body']['type']);
$this->assertEquals('available', $enumResponse['body']['status']);
$this->assertEquals($enum['body']['required'], $enumResponse['body']['required']);
$this->assertEquals($enum['body']['array'], $enumResponse['body']['array']);
$this->assertEquals($enum['body']['format'], $enumResponse['body']['format']);
$this->assertEquals($enum['body']['default'], $enumResponse['body']['default']);
$this->assertEquals($enum['body']['elements'], $enumResponse['body']['elements']);
$this->assertEquals(200, $ipResponse['headers']['status-code']);
$this->assertEquals($ip['body']['key'], $ipResponse['body']['key']);
$this->assertEquals($ip['body']['type'], $ipResponse['body']['type']);
@ -378,12 +416,12 @@ trait DatabaseBase
]));
$this->assertEquals(200, $attributes['headers']['status-code']);
$this->assertEquals(7, $attributes['body']['sum']);
$this->assertEquals(8, $attributes['body']['sum']);
$attributes = $attributes['body']['attributes'];
$this->assertIsArray($attributes);
$this->assertCount(7, $attributes);
$this->assertCount(8, $attributes);
$this->assertEquals($stringResponse['body']['key'], $attributes[0]['key']);
$this->assertEquals($stringResponse['body']['type'], $attributes[0]['type']);
@ -401,46 +439,55 @@ trait DatabaseBase
$this->assertEquals($emailResponse['body']['default'], $attributes[1]['default']);
$this->assertEquals($emailResponse['body']['format'], $attributes[1]['format']);
$this->assertEquals($ipResponse['body']['key'], $attributes[2]['key']);
$this->assertEquals($ipResponse['body']['type'], $attributes[2]['type']);
$this->assertEquals($ipResponse['body']['status'], $attributes[2]['status']);
$this->assertEquals($ipResponse['body']['required'], $attributes[2]['required']);
$this->assertEquals($ipResponse['body']['array'], $attributes[2]['array']);
$this->assertEquals($ipResponse['body']['default'], $attributes[2]['default']);
$this->assertEquals($ipResponse['body']['format'], $attributes[2]['format']);
$this->assertEquals($enumResponse['body']['key'], $attributes[2]['key']);
$this->assertEquals($enumResponse['body']['type'], $attributes[2]['type']);
$this->assertEquals($enumResponse['body']['status'], $attributes[2]['status']);
$this->assertEquals($enumResponse['body']['required'], $attributes[2]['required']);
$this->assertEquals($enumResponse['body']['array'], $attributes[2]['array']);
$this->assertEquals($enumResponse['body']['default'], $attributes[2]['default']);
$this->assertEquals($enumResponse['body']['format'], $attributes[2]['format']);
$this->assertEquals($enumResponse['body']['elements'], $attributes[2]['elements']);
$this->assertEquals($urlResponse['body']['key'], $attributes[3]['key']);
$this->assertEquals($urlResponse['body']['type'], $attributes[3]['type']);
$this->assertEquals($urlResponse['body']['status'], $attributes[3]['status']);
$this->assertEquals($urlResponse['body']['required'], $attributes[3]['required']);
$this->assertEquals($urlResponse['body']['array'], $attributes[3]['array']);
$this->assertEquals($urlResponse['body']['default'], $attributes[3]['default']);
$this->assertEquals($urlResponse['body']['format'], $attributes[3]['format']);
$this->assertEquals($ipResponse['body']['key'], $attributes[3]['key']);
$this->assertEquals($ipResponse['body']['type'], $attributes[3]['type']);
$this->assertEquals($ipResponse['body']['status'], $attributes[3]['status']);
$this->assertEquals($ipResponse['body']['required'], $attributes[3]['required']);
$this->assertEquals($ipResponse['body']['array'], $attributes[3]['array']);
$this->assertEquals($ipResponse['body']['default'], $attributes[3]['default']);
$this->assertEquals($ipResponse['body']['format'], $attributes[3]['format']);
$this->assertEquals($integerResponse['body']['key'], $attributes[4]['key']);
$this->assertEquals($integerResponse['body']['type'], $attributes[4]['type']);
$this->assertEquals($integerResponse['body']['status'], $attributes[4]['status']);
$this->assertEquals($integerResponse['body']['required'], $attributes[4]['required']);
$this->assertEquals($integerResponse['body']['array'], $attributes[4]['array']);
$this->assertEquals($integerResponse['body']['default'], $attributes[4]['default']);
$this->assertEquals($integerResponse['body']['min'], $attributes[4]['min']);
$this->assertEquals($integerResponse['body']['max'], $attributes[4]['max']);
$this->assertEquals($urlResponse['body']['key'], $attributes[4]['key']);
$this->assertEquals($urlResponse['body']['type'], $attributes[4]['type']);
$this->assertEquals($urlResponse['body']['status'], $attributes[4]['status']);
$this->assertEquals($urlResponse['body']['required'], $attributes[4]['required']);
$this->assertEquals($urlResponse['body']['array'], $attributes[4]['array']);
$this->assertEquals($urlResponse['body']['default'], $attributes[4]['default']);
$this->assertEquals($urlResponse['body']['format'], $attributes[4]['format']);
$this->assertEquals($floatResponse['body']['key'], $attributes[5]['key']);
$this->assertEquals($floatResponse['body']['type'], $attributes[5]['type']);
$this->assertEquals($floatResponse['body']['status'], $attributes[5]['status']);
$this->assertEquals($floatResponse['body']['required'], $attributes[5]['required']);
$this->assertEquals($floatResponse['body']['array'], $attributes[5]['array']);
$this->assertEquals($floatResponse['body']['default'], $attributes[5]['default']);
$this->assertEquals($floatResponse['body']['min'], $attributes[5]['min']);
$this->assertEquals($floatResponse['body']['max'], $attributes[5]['max']);
$this->assertEquals($integerResponse['body']['key'], $attributes[5]['key']);
$this->assertEquals($integerResponse['body']['type'], $attributes[5]['type']);
$this->assertEquals($integerResponse['body']['status'], $attributes[5]['status']);
$this->assertEquals($integerResponse['body']['required'], $attributes[5]['required']);
$this->assertEquals($integerResponse['body']['array'], $attributes[5]['array']);
$this->assertEquals($integerResponse['body']['default'], $attributes[5]['default']);
$this->assertEquals($integerResponse['body']['min'], $attributes[5]['min']);
$this->assertEquals($integerResponse['body']['max'], $attributes[5]['max']);
$this->assertEquals($booleanResponse['body']['key'], $attributes[6]['key']);
$this->assertEquals($booleanResponse['body']['type'], $attributes[6]['type']);
$this->assertEquals($booleanResponse['body']['status'], $attributes[6]['status']);
$this->assertEquals($booleanResponse['body']['required'], $attributes[6]['required']);
$this->assertEquals($booleanResponse['body']['array'], $attributes[6]['array']);
$this->assertEquals($booleanResponse['body']['default'], $attributes[6]['default']);
$this->assertEquals($floatResponse['body']['key'], $attributes[6]['key']);
$this->assertEquals($floatResponse['body']['type'], $attributes[6]['type']);
$this->assertEquals($floatResponse['body']['status'], $attributes[6]['status']);
$this->assertEquals($floatResponse['body']['required'], $attributes[6]['required']);
$this->assertEquals($floatResponse['body']['array'], $attributes[6]['array']);
$this->assertEquals($floatResponse['body']['default'], $attributes[6]['default']);
$this->assertEquals($floatResponse['body']['min'], $attributes[6]['min']);
$this->assertEquals($floatResponse['body']['max'], $attributes[6]['max']);
$this->assertEquals($booleanResponse['body']['key'], $attributes[7]['key']);
$this->assertEquals($booleanResponse['body']['type'], $attributes[7]['type']);
$this->assertEquals($booleanResponse['body']['status'], $attributes[7]['status']);
$this->assertEquals($booleanResponse['body']['required'], $attributes[7]['required']);
$this->assertEquals($booleanResponse['body']['array'], $attributes[7]['array']);
$this->assertEquals($booleanResponse['body']['default'], $attributes[7]['default']);
$collection = $this->client->call(Client::METHOD_GET, '/database/collections/' . $collectionId, array_merge([
'content-type' => 'application/json',
@ -453,7 +500,7 @@ trait DatabaseBase
$attributes = $collection['body']['attributes'];
$this->assertIsArray($attributes);
$this->assertCount(7, $attributes);
$this->assertCount(8, $attributes);
$this->assertEquals($stringResponse['body']['key'], $attributes[0]['key']);
$this->assertEquals($stringResponse['body']['type'], $attributes[0]['type']);
@ -471,46 +518,72 @@ trait DatabaseBase
$this->assertEquals($emailResponse['body']['default'], $attributes[1]['default']);
$this->assertEquals($emailResponse['body']['format'], $attributes[1]['format']);
$this->assertEquals($ipResponse['body']['key'], $attributes[2]['key']);
$this->assertEquals($ipResponse['body']['type'], $attributes[2]['type']);
$this->assertEquals($ipResponse['body']['status'], $attributes[2]['status']);
$this->assertEquals($ipResponse['body']['required'], $attributes[2]['required']);
$this->assertEquals($ipResponse['body']['array'], $attributes[2]['array']);
$this->assertEquals($ipResponse['body']['default'], $attributes[2]['default']);
$this->assertEquals($ipResponse['body']['format'], $attributes[2]['format']);
$this->assertEquals($enumResponse['body']['key'], $attributes[2]['key']);
$this->assertEquals($enumResponse['body']['type'], $attributes[2]['type']);
$this->assertEquals($enumResponse['body']['status'], $attributes[2]['status']);
$this->assertEquals($enumResponse['body']['required'], $attributes[2]['required']);
$this->assertEquals($enumResponse['body']['array'], $attributes[2]['array']);
$this->assertEquals($enumResponse['body']['default'], $attributes[2]['default']);
$this->assertEquals($enumResponse['body']['format'], $attributes[2]['format']);
$this->assertEquals($enumResponse['body']['elements'], $attributes[2]['elements']);
$this->assertEquals($urlResponse['body']['key'], $attributes[3]['key']);
$this->assertEquals($urlResponse['body']['type'], $attributes[3]['type']);
$this->assertEquals($urlResponse['body']['status'], $attributes[3]['status']);
$this->assertEquals($urlResponse['body']['required'], $attributes[3]['required']);
$this->assertEquals($urlResponse['body']['array'], $attributes[3]['array']);
$this->assertEquals($urlResponse['body']['default'], $attributes[3]['default']);
$this->assertEquals($urlResponse['body']['format'], $attributes[3]['format']);
$this->assertEquals($ipResponse['body']['key'], $attributes[3]['key']);
$this->assertEquals($ipResponse['body']['type'], $attributes[3]['type']);
$this->assertEquals($ipResponse['body']['status'], $attributes[3]['status']);
$this->assertEquals($ipResponse['body']['required'], $attributes[3]['required']);
$this->assertEquals($ipResponse['body']['array'], $attributes[3]['array']);
$this->assertEquals($ipResponse['body']['default'], $attributes[3]['default']);
$this->assertEquals($ipResponse['body']['format'], $attributes[3]['format']);
$this->assertEquals($integerResponse['body']['key'], $attributes[4]['key']);
$this->assertEquals($integerResponse['body']['type'], $attributes[4]['type']);
$this->assertEquals($integerResponse['body']['status'], $attributes[4]['status']);
$this->assertEquals($integerResponse['body']['required'], $attributes[4]['required']);
$this->assertEquals($integerResponse['body']['array'], $attributes[4]['array']);
$this->assertEquals($integerResponse['body']['default'], $attributes[4]['default']);
$this->assertEquals($integerResponse['body']['min'], $attributes[4]['min']);
$this->assertEquals($integerResponse['body']['max'], $attributes[4]['max']);
$this->assertEquals($urlResponse['body']['key'], $attributes[4]['key']);
$this->assertEquals($urlResponse['body']['type'], $attributes[4]['type']);
$this->assertEquals($urlResponse['body']['status'], $attributes[4]['status']);
$this->assertEquals($urlResponse['body']['required'], $attributes[4]['required']);
$this->assertEquals($urlResponse['body']['array'], $attributes[4]['array']);
$this->assertEquals($urlResponse['body']['default'], $attributes[4]['default']);
$this->assertEquals($urlResponse['body']['format'], $attributes[4]['format']);
$this->assertEquals($floatResponse['body']['key'], $attributes[5]['key']);
$this->assertEquals($floatResponse['body']['type'], $attributes[5]['type']);
$this->assertEquals($floatResponse['body']['status'], $attributes[5]['status']);
$this->assertEquals($floatResponse['body']['required'], $attributes[5]['required']);
$this->assertEquals($floatResponse['body']['array'], $attributes[5]['array']);
$this->assertEquals($floatResponse['body']['default'], $attributes[5]['default']);
$this->assertEquals($floatResponse['body']['min'], $attributes[5]['min']);
$this->assertEquals($floatResponse['body']['max'], $attributes[5]['max']);
$this->assertEquals($integerResponse['body']['key'], $attributes[5]['key']);
$this->assertEquals($integerResponse['body']['type'], $attributes[5]['type']);
$this->assertEquals($integerResponse['body']['status'], $attributes[5]['status']);
$this->assertEquals($integerResponse['body']['required'], $attributes[5]['required']);
$this->assertEquals($integerResponse['body']['array'], $attributes[5]['array']);
$this->assertEquals($integerResponse['body']['default'], $attributes[5]['default']);
$this->assertEquals($integerResponse['body']['min'], $attributes[5]['min']);
$this->assertEquals($integerResponse['body']['max'], $attributes[5]['max']);
$this->assertEquals($booleanResponse['body']['key'], $attributes[6]['key']);
$this->assertEquals($booleanResponse['body']['type'], $attributes[6]['type']);
$this->assertEquals($booleanResponse['body']['status'], $attributes[6]['status']);
$this->assertEquals($booleanResponse['body']['required'], $attributes[6]['required']);
$this->assertEquals($booleanResponse['body']['array'], $attributes[6]['array']);
$this->assertEquals($booleanResponse['body']['default'], $attributes[6]['default']);
$this->assertEquals($floatResponse['body']['key'], $attributes[6]['key']);
$this->assertEquals($floatResponse['body']['type'], $attributes[6]['type']);
$this->assertEquals($floatResponse['body']['status'], $attributes[6]['status']);
$this->assertEquals($floatResponse['body']['required'], $attributes[6]['required']);
$this->assertEquals($floatResponse['body']['array'], $attributes[6]['array']);
$this->assertEquals($floatResponse['body']['default'], $attributes[6]['default']);
$this->assertEquals($floatResponse['body']['min'], $attributes[6]['min']);
$this->assertEquals($floatResponse['body']['max'], $attributes[6]['max']);
$this->assertEquals($booleanResponse['body']['key'], $attributes[7]['key']);
$this->assertEquals($booleanResponse['body']['type'], $attributes[7]['type']);
$this->assertEquals($booleanResponse['body']['status'], $attributes[7]['status']);
$this->assertEquals($booleanResponse['body']['required'], $attributes[7]['required']);
$this->assertEquals($booleanResponse['body']['array'], $attributes[7]['array']);
$this->assertEquals($booleanResponse['body']['default'], $attributes[7]['default']);
/**
* Test for FAILURE
*/
$badEnum = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/attributes/enum', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'attributeId' => 'enum',
'elements' => ['yes', 'no', ''],
'required' => false,
'default' => 'maybe',
]);
$this->assertEquals(400, $badEnum['headers']['status-code']);
$this->assertEquals('Each enum element must not be empty', $badEnum['body']['message']);
return $data;
}
@ -1176,6 +1249,16 @@ trait DatabaseBase
'required' => false,
]);
$enum = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/attributes/enum', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'attributeId' => 'enum',
'elements' => ['yes', 'no', 'maybe'],
'required' => false,
]);
$ip = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/attributes/ip', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -1284,7 +1367,7 @@ trait DatabaseBase
'x-appwrite-key' => $this->getProject()['apiKey'],
]), []);
$this->assertCount(7, $collection['body']['attributes']);
$this->assertCount(8, $collection['body']['attributes']);
/**
* Test for successful validation
@ -1302,6 +1385,18 @@ trait DatabaseBase
'write' => ['user:'.$this->getUser()['$id']],
]);
$goodEnum = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'enum' => 'yes',
],
'read' => ['user:'.$this->getUser()['$id']],
'write' => ['user:'.$this->getUser()['$id']],
]);
$goodIp = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -1375,6 +1470,7 @@ trait DatabaseBase
]);
$this->assertEquals(201, $goodEmail['headers']['status-code']);
$this->assertEquals(201, $goodEnum['headers']['status-code']);
$this->assertEquals(201, $goodIp['headers']['status-code']);
$this->assertEquals(201, $goodUrl['headers']['status-code']);
$this->assertEquals(201, $goodRange['headers']['status-code']);
@ -1398,6 +1494,18 @@ trait DatabaseBase
'write' => ['user:'.$this->getUser()['$id']],
]);
$badEnum = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'documentId' => 'unique()',
'data' => [
'enum' => 'badEnum',
],
'read' => ['user:'.$this->getUser()['$id']],
'write' => ['user:'.$this->getUser()['$id']],
]);
$badIp = $this->client->call(Client::METHOD_POST, '/database/collections/' . $collectionId . '/documents', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@ -1471,6 +1579,7 @@ trait DatabaseBase
]);
$this->assertEquals(400, $badEmail['headers']['status-code']);
$this->assertEquals(400, $badEnum['headers']['status-code']);
$this->assertEquals(400, $badIp['headers']['status-code']);
$this->assertEquals(400, $badUrl['headers']['status-code']);
$this->assertEquals(400, $badRange['headers']['status-code']);
@ -1478,6 +1587,7 @@ trait DatabaseBase
$this->assertEquals(400, $tooHigh['headers']['status-code']);
$this->assertEquals(400, $tooLow['headers']['status-code']);
$this->assertEquals('Invalid document structure: Attribute "email" has invalid format. Value must be a valid email address', $badEmail['body']['message']);
$this->assertEquals('Invalid document structure: Attribute "enum" has invalid format. Value must be one of (yes, no, maybe)', $badEnum['body']['message']);
$this->assertEquals('Invalid document structure: Attribute "ip" has invalid format. Value must be a valid IP address', $badIp['body']['message']);
$this->assertEquals('Invalid document structure: Attribute "url" has invalid format. Value must be a valid URL', $badUrl['body']['message']);
$this->assertEquals('Invalid document structure: Attribute "range" has invalid format. Value must be a valid range between 1 and 10', $badRange['body']['message']);