diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index 2ab514f91c..086ad4c5e7 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -3,7 +3,6 @@ namespace Appwrite\Utopia; use Exception; -use Swoole\Http\Request as SwooleRequest; use Utopia\Swoole\Response as SwooleResponse; use Swoole\Http\Response as SwooleHTTPResponse; use Utopia\Database\Document; @@ -238,113 +237,115 @@ class Response extends SwooleResponse */ public function __construct(SwooleHTTPResponse $response) { - $this - // General - ->setModel(new None()) - ->setModel(new Any()) - ->setModel(new Error()) - ->setModel(new ErrorDev()) - // Lists - ->setModel(new BaseList('Documents List', self::MODEL_DOCUMENT_LIST, 'documents', self::MODEL_DOCUMENT)) - ->setModel(new BaseList('Collections List', self::MODEL_COLLECTION_LIST, 'collections', self::MODEL_COLLECTION)) - ->setModel(new BaseList('Databases List', self::MODEL_DATABASE_LIST, 'databases', self::MODEL_DATABASE)) - ->setModel(new BaseList('Indexes List', self::MODEL_INDEX_LIST, 'indexes', self::MODEL_INDEX)) - ->setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER)) - ->setModel(new BaseList('Sessions List', self::MODEL_SESSION_LIST, 'sessions', self::MODEL_SESSION)) - ->setModel(new BaseList('Logs List', self::MODEL_LOG_LIST, 'logs', self::MODEL_LOG)) - ->setModel(new BaseList('Files List', self::MODEL_FILE_LIST, 'files', self::MODEL_FILE)) - ->setModel(new BaseList('Buckets List', self::MODEL_BUCKET_LIST, 'buckets', self::MODEL_BUCKET)) - ->setModel(new BaseList('Teams List', self::MODEL_TEAM_LIST, 'teams', self::MODEL_TEAM)) - ->setModel(new BaseList('Memberships List', self::MODEL_MEMBERSHIP_LIST, 'memberships', self::MODEL_MEMBERSHIP)) - ->setModel(new BaseList('Functions List', self::MODEL_FUNCTION_LIST, 'functions', self::MODEL_FUNCTION)) - ->setModel(new BaseList('Runtimes List', self::MODEL_RUNTIME_LIST, 'runtimes', self::MODEL_RUNTIME)) - ->setModel(new BaseList('Deployments List', self::MODEL_DEPLOYMENT_LIST, 'deployments', self::MODEL_DEPLOYMENT)) - ->setModel(new BaseList('Executions List', self::MODEL_EXECUTION_LIST, 'executions', self::MODEL_EXECUTION)) - ->setModel(new BaseList('Builds List', self::MODEL_BUILD_LIST, 'builds', self::MODEL_BUILD)) // Not used anywhere yet - ->setModel(new BaseList('Projects List', self::MODEL_PROJECT_LIST, 'projects', self::MODEL_PROJECT, true, false)) - ->setModel(new BaseList('Webhooks List', self::MODEL_WEBHOOK_LIST, 'webhooks', self::MODEL_WEBHOOK, true, false)) - ->setModel(new BaseList('API Keys List', self::MODEL_KEY_LIST, 'keys', self::MODEL_KEY, true, false)) - ->setModel(new BaseList('Providers List', self::MODEL_PROVIDER_LIST, 'platforms', self::MODEL_PROVIDER, true, false)) - ->setModel(new BaseList('Platforms List', self::MODEL_PLATFORM_LIST, 'platforms', self::MODEL_PLATFORM, true, false)) - ->setModel(new BaseList('Domains List', self::MODEL_DOMAIN_LIST, 'domains', self::MODEL_DOMAIN, true, false)) - ->setModel(new BaseList('Countries List', self::MODEL_COUNTRY_LIST, 'countries', self::MODEL_COUNTRY)) - ->setModel(new BaseList('Continents List', self::MODEL_CONTINENT_LIST, 'continents', self::MODEL_CONTINENT)) - ->setModel(new BaseList('Languages List', self::MODEL_LANGUAGE_LIST, 'languages', self::MODEL_LANGUAGE)) - ->setModel(new BaseList('Currencies List', self::MODEL_CURRENCY_LIST, 'currencies', self::MODEL_CURRENCY)) - ->setModel(new BaseList('Phones List', self::MODEL_PHONE_LIST, 'phones', self::MODEL_PHONE)) - ->setModel(new BaseList('Metric List', self::MODEL_METRIC_LIST, 'metrics', self::MODEL_METRIC, true, false)) - ->setModel(new BaseList('Variables List', self::MODEL_VARIABLE_LIST, 'variables', self::MODEL_VARIABLE)) - // Entities - ->setModel(new Database()) - ->setModel(new Collection()) - ->setModel(new Attribute()) - ->setModel(new AttributeList()) - ->setModel(new AttributeString()) - ->setModel(new AttributeInteger()) - ->setModel(new AttributeFloat()) - ->setModel(new AttributeBoolean()) - ->setModel(new AttributeEmail()) - ->setModel(new AttributeEnum()) - ->setModel(new AttributeIP()) - ->setModel(new AttributeURL()) - ->setModel(new AttributeDatetime()) - ->setModel(new Index()) - ->setModel(new ModelDocument()) - ->setModel(new Log()) - ->setModel(new User()) - ->setModel(new AlgoMd5()) - ->setModel(new AlgoSha()) - ->setModel(new AlgoPhpass()) - ->setModel(new AlgoBcrypt()) - ->setModel(new AlgoScrypt()) - ->setModel(new AlgoScryptModified()) - ->setModel(new AlgoArgon2()) - ->setModel(new Account()) - ->setModel(new Preferences()) - ->setModel(new Session()) - ->setModel(new Token()) - ->setModel(new JWT()) - ->setModel(new Locale()) - ->setModel(new File()) - ->setModel(new Bucket()) - ->setModel(new Team()) - ->setModel(new Membership()) - ->setModel(new Func()) - ->setModel(new Runtime()) - ->setModel(new Deployment()) - ->setModel(new Execution()) - ->setModel(new Build()) - ->setModel(new Project()) - ->setModel(new Webhook()) - ->setModel(new Key()) - ->setModel(new Domain()) - ->setModel(new Provider()) - ->setModel(new Platform()) - ->setModel(new Variable()) - ->setModel(new Country()) - ->setModel(new Continent()) - ->setModel(new Language()) - ->setModel(new Currency()) - ->setModel(new Phone()) - ->setModel(new HealthAntivirus()) - ->setModel(new HealthQueue()) - ->setModel(new HealthStatus()) - ->setModel(new HealthTime()) - ->setModel(new HealthVersion()) - ->setModel(new Metric()) - ->setModel(new UsageDatabases()) - ->setModel(new UsageDatabase()) - ->setModel(new UsageCollection()) - ->setModel(new UsageUsers()) - ->setModel(new UsageStorage()) - ->setModel(new UsageBuckets()) - ->setModel(new UsageFunctions()) - ->setModel(new UsageFunction()) - ->setModel(new UsageProject()) - // Verification - // Recovery - // Tests (keep last) - ->setModel(new Mock()); + if (empty(self::$models)) { + self + // General + ::setModel(new None()) + ::setModel(new Any()) + ::setModel(new Error()) + ::setModel(new ErrorDev()) + // Lists + ::setModel(new BaseList('Documents List', self::MODEL_DOCUMENT_LIST, 'documents', self::MODEL_DOCUMENT)) + ::setModel(new BaseList('Collections List', self::MODEL_COLLECTION_LIST, 'collections', self::MODEL_COLLECTION)) + ::setModel(new BaseList('Databases List', self::MODEL_DATABASE_LIST, 'databases', self::MODEL_DATABASE)) + ::setModel(new BaseList('Indexes List', self::MODEL_INDEX_LIST, 'indexes', self::MODEL_INDEX)) + ::setModel(new BaseList('Users List', self::MODEL_USER_LIST, 'users', self::MODEL_USER)) + ::setModel(new BaseList('Sessions List', self::MODEL_SESSION_LIST, 'sessions', self::MODEL_SESSION)) + ::setModel(new BaseList('Logs List', self::MODEL_LOG_LIST, 'logs', self::MODEL_LOG)) + ::setModel(new BaseList('Files List', self::MODEL_FILE_LIST, 'files', self::MODEL_FILE)) + ::setModel(new BaseList('Buckets List', self::MODEL_BUCKET_LIST, 'buckets', self::MODEL_BUCKET)) + ::setModel(new BaseList('Teams List', self::MODEL_TEAM_LIST, 'teams', self::MODEL_TEAM)) + ::setModel(new BaseList('Memberships List', self::MODEL_MEMBERSHIP_LIST, 'memberships', self::MODEL_MEMBERSHIP)) + ::setModel(new BaseList('Functions List', self::MODEL_FUNCTION_LIST, 'functions', self::MODEL_FUNCTION)) + ::setModel(new BaseList('Runtimes List', self::MODEL_RUNTIME_LIST, 'runtimes', self::MODEL_RUNTIME)) + ::setModel(new BaseList('Deployments List', self::MODEL_DEPLOYMENT_LIST, 'deployments', self::MODEL_DEPLOYMENT)) + ::setModel(new BaseList('Executions List', self::MODEL_EXECUTION_LIST, 'executions', self::MODEL_EXECUTION)) + ::setModel(new BaseList('Builds List', self::MODEL_BUILD_LIST, 'builds', self::MODEL_BUILD)) // Not used anywhere yet + ::setModel(new BaseList('Projects List', self::MODEL_PROJECT_LIST, 'projects', self::MODEL_PROJECT, true, false)) + ::setModel(new BaseList('Webhooks List', self::MODEL_WEBHOOK_LIST, 'webhooks', self::MODEL_WEBHOOK, true, false)) + ::setModel(new BaseList('API Keys List', self::MODEL_KEY_LIST, 'keys', self::MODEL_KEY, true, false)) + ::setModel(new BaseList('Providers List', self::MODEL_PROVIDER_LIST, 'platforms', self::MODEL_PROVIDER, true, false)) + ::setModel(new BaseList('Platforms List', self::MODEL_PLATFORM_LIST, 'platforms', self::MODEL_PLATFORM, true, false)) + ::setModel(new BaseList('Domains List', self::MODEL_DOMAIN_LIST, 'domains', self::MODEL_DOMAIN, true, false)) + ::setModel(new BaseList('Countries List', self::MODEL_COUNTRY_LIST, 'countries', self::MODEL_COUNTRY)) + ::setModel(new BaseList('Continents List', self::MODEL_CONTINENT_LIST, 'continents', self::MODEL_CONTINENT)) + ::setModel(new BaseList('Languages List', self::MODEL_LANGUAGE_LIST, 'languages', self::MODEL_LANGUAGE)) + ::setModel(new BaseList('Currencies List', self::MODEL_CURRENCY_LIST, 'currencies', self::MODEL_CURRENCY)) + ::setModel(new BaseList('Phones List', self::MODEL_PHONE_LIST, 'phones', self::MODEL_PHONE)) + ::setModel(new BaseList('Metric List', self::MODEL_METRIC_LIST, 'metrics', self::MODEL_METRIC, true, false)) + ::setModel(new BaseList('Variables List', self::MODEL_VARIABLE_LIST, 'variables', self::MODEL_VARIABLE)) + // Entities + ::setModel(new Database()) + ::setModel(new Collection()) + ::setModel(new Attribute()) + ::setModel(new AttributeList()) + ::setModel(new AttributeString()) + ::setModel(new AttributeInteger()) + ::setModel(new AttributeFloat()) + ::setModel(new AttributeBoolean()) + ::setModel(new AttributeEmail()) + ::setModel(new AttributeEnum()) + ::setModel(new AttributeIP()) + ::setModel(new AttributeURL()) + ::setModel(new AttributeDatetime()) + ::setModel(new Index()) + ::setModel(new ModelDocument()) + ::setModel(new Log()) + ::setModel(new User()) + ::setModel(new AlgoMd5()) + ::setModel(new AlgoSha()) + ::setModel(new AlgoPhpass()) + ::setModel(new AlgoBcrypt()) + ::setModel(new AlgoScrypt()) + ::setModel(new AlgoScryptModified()) + ::setModel(new AlgoArgon2()) + ::setModel(new Account()) + ::setModel(new Preferences()) + ::setModel(new Session()) + ::setModel(new Token()) + ::setModel(new JWT()) + ::setModel(new Locale()) + ::setModel(new File()) + ::setModel(new Bucket()) + ::setModel(new Team()) + ::setModel(new Membership()) + ::setModel(new Func()) + ::setModel(new Runtime()) + ::setModel(new Deployment()) + ::setModel(new Execution()) + ::setModel(new Build()) + ::setModel(new Project()) + ::setModel(new Webhook()) + ::setModel(new Key()) + ::setModel(new Domain()) + ::setModel(new Provider()) + ::setModel(new Platform()) + ::setModel(new Variable()) + ::setModel(new Country()) + ::setModel(new Continent()) + ::setModel(new Language()) + ::setModel(new Currency()) + ::setModel(new Phone()) + ::setModel(new HealthAntivirus()) + ::setModel(new HealthQueue()) + ::setModel(new HealthStatus()) + ::setModel(new HealthTime()) + ::setModel(new HealthVersion()) + ::setModel(new Metric()) + ::setModel(new UsageDatabases()) + ::setModel(new UsageDatabase()) + ::setModel(new UsageCollection()) + ::setModel(new UsageUsers()) + ::setModel(new UsageStorage()) + ::setModel(new UsageBuckets()) + ::setModel(new UsageFunctions()) + ::setModel(new UsageFunction()) + ::setModel(new UsageProject()) + // Verification + // Recovery + // Tests (keep last) + ::setModel(new Mock()); + } parent::__construct($response); } @@ -358,18 +359,16 @@ class Response extends SwooleResponse /** * List of defined output objects */ - protected $models = []; + protected static array $models = []; /** * Set Model Object - * - * @return self */ - public function setModel(Model $instance) + public static function setModel(Model $instance): static { - $this->models[$instance->getType()] = $instance; + self::$models[$instance->getType()] = $instance; - return $this; + return static ; } /** @@ -379,23 +378,19 @@ class Response extends SwooleResponse * @return Model * @throws Exception */ - public function getModel(string $key): Model + public static function getModel(string $key): Model { - if (!isset($this->models[$key])) { - throw new Exception('Undefined model: ' . $key); - } - - return $this->models[$key]; + return self::$models[$key] ?? throw new Exception('Undefined model: ' . $key); } /** * Get Models List * - * @return Model[] + * @return array */ - public function getModels(): array + public static function getModels(): array { - return $this->models; + return self::$models; } /** @@ -451,9 +446,9 @@ class Response extends SwooleResponse */ public function output(Document $document, string $model): array { - $data = $document; - $model = $this->getModel($model); - $output = []; + $data = $document; + $model = $this->getModel($model); + $output = []; $document = $model->filter($document); @@ -464,23 +459,19 @@ class Response extends SwooleResponse } foreach ($model->getRules() as $key => $rule) { - if (!$document->isSet($key) && $rule['required']) { // do not set attribute in response if not required - if (\array_key_exists('default', $rule)) { - $document->setAttribute($key, $rule['default']); - } else { - throw new Exception('Model ' . $model->getName() . ' is missing response key: ' . $key); - } + if (!$document->isSet($key) && $rule->isRequired()) { // do not set attribute in response if not required + $document->setAttribute($key, $rule->getDefault()); } - if ($rule['array']) { + if ($rule->isArray()) { if (!is_array($data[$key])) { throw new Exception($key . ' must be an array of type ' . $rule['type']); } foreach ($data[$key] as $index => $item) { if ($item instanceof Document) { - if (\is_array($rule['type'])) { - foreach ($rule['type'] as $type) { + if (\is_array($rule->getType())) { + foreach ($rule->getType() as $type) { $condition = false; foreach ($this->getModel($type)->conditions as $attribute => $val) { $condition = $item->getAttribute($attribute) === $val; @@ -494,7 +485,7 @@ class Response extends SwooleResponse } } } else { - $ruleType = $rule['type']; + $ruleType = $rule->getType(); } if (!array_key_exists($ruleType, $this->models)) { @@ -597,6 +588,6 @@ class Response extends SwooleResponse */ public static function hasFilter(): bool { - return self::$filter != null; + return self::$filter !== null; } } diff --git a/src/Appwrite/Utopia/Response/Attribute/Name.php b/src/Appwrite/Utopia/Response/Attribute/Name.php new file mode 100644 index 0000000000..538241e4c1 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Attribute/Name.php @@ -0,0 +1,14 @@ +type = $type; + + return $this; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function getName(): string + { + return $this->name; + } + + public function getType(): string|array + { + return $this->type; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getDefault(): string + { + return $this->default; + } + + public function getExample(): string + { + return $this->example; + } + + public function isRequired(): bool + { + return $this->required; + } + + public function isArray(): bool + { + return $this->array; + } +} diff --git a/src/Appwrite/Utopia/Response/Attribute/Type.php b/src/Appwrite/Utopia/Response/Attribute/Type.php new file mode 100644 index 0000000000..aaca274579 --- /dev/null +++ b/src/Appwrite/Utopia/Response/Attribute/Type.php @@ -0,0 +1,14 @@ + */ protected array $rules = []; - - /** - * @var array - */ + protected string $name; + protected string $type; + protected bool $none = false; + protected bool $any = false; + protected bool $public = true; public array $conditions = []; + public function __construct() + { + $reflection = new \ReflectionClass($this); + + $this->name = $this->getAttribute($reflection, Name::class); + $this->type = $this->getAttribute($reflection, Type::class); + + $options = $this->getAttribute($reflection, Options::class); + if ($options !== null) { + $options = $options->newInstance(); + $this->none = $options->none; + $this->any = $options->any; + $this->public = $options->public; + } + + foreach ($reflection->getProperties() as $property) { + $attribute = $this->getAttribute($property, Type::class); + if ($attribute === null) { + continue; + } + + /** @var Rule $rule */ + $rule = $attribute->newInstance(); + $name = $property->getName(); + $type = match ($property->getType()) { + 'string' => self::TYPE_STRING, + 'int' => self::TYPE_INTEGER, + 'float' => self::TYPE_FLOAT, + 'bool' => self::TYPE_BOOLEAN, + 'array' => self::TYPE_JSON, + 'object' => self::TYPE_JSON, + 'DateTime' => self::TYPE_DATETIME, + default => throw new \Exception('Unknown type: ' . $property->getType()), + }; + + $rule + ->setName($name) + ->setType($type); + + $this->rules[$name] = $rule; + } + } - /** - * Filter Document Structure - * - * @return Document - */ public function filter(Document $document): Document { return $document; } /** - * Get Name - * - * @return string - */ - abstract public function getName(): string; - - /** - * Get Collection - * - * @return string - */ - abstract public function getType(): string; - - /** - * Get Rules - * - * @return array + * @return array */ public function getRules(): array { return $this->rules; } - /** - * Add a New Rule - * If rule is an array of documents with varying models - * - * @param string $key - * @param array $options - */ - protected function addRule(string $key, array $options): self + public function getType(): string { - $this->rules[$key] = array_merge([ - 'required' => true, - 'array' => false, - 'description' => '', - 'example' => '' - ], $options); + return $this->type; + } - return $this; + public function getName(): string + { + return $this->name; + } + + public function getRequired() + { + return \array_filter($this->rules, fn (Rule $rule) => $rule->isRequired()); } - /** - * Delete an existing Rule - * If rule exists, it will be removed - * - * @param string $key - * @param array $options - */ protected function removeRule(string $key): self { if (isset($this->rules[$key])) { @@ -109,52 +110,23 @@ abstract class Model return $this; } - public function getRequired() - { - $list = []; - - foreach ($this->rules as $key => $rule) { - if ($rule['required'] ?? false) { - $list[] = $key; - } - } - - return $list; - } - - /** - * Is None - * - * Use to check if response is empty - * - * @return bool - */ public function isNone(): bool { return $this->none; } - /** - * Is Any - * - * Use to check if response is a wildcard - * - * @return bool - */ public function isAny(): bool { return $this->any; } - /** - * Is Public - * - * Should this model be publicly available in docs and spec files? - * - * @return bool - */ public function isPublic(): bool { return $this->public; } + + private function getAttribute(ReflectionClass | ReflectionProperty $reflection, string $class): ?ReflectionAttribute + { + return $reflection->getAttributes($class)[0] ?? null; + } } diff --git a/src/Appwrite/Utopia/Response/Model/Account.php b/src/Appwrite/Utopia/Response/Model/Account.php index bfcd7ab7d8..746d6184f7 100644 --- a/src/Appwrite/Utopia/Response/Model/Account.php +++ b/src/Appwrite/Utopia/Response/Model/Account.php @@ -3,7 +3,11 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Type; +#[Name('Account')] +#[Type(Response::MODEL_ACCOUNT)] class Account extends User { public function __construct() @@ -15,24 +19,4 @@ class Account extends User ->removeRule('hash') ->removeRule('hashOptions'); } - - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'Account'; - } - - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ACCOUNT; - } } diff --git a/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php b/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php index 3e162bb905..00689d470d 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoArgon2.php @@ -3,58 +3,40 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Type; use Appwrite\Utopia\Response\Model; +use Appwrite\Utopia\Response\Rule; +#[Name('AlgoArgon2')] +#[Type(Response::MODEL_ALGO_ARGON2)] class AlgoArgon2 extends Model { - public function __construct() - { - // No options if imported. If hashed by Appwrite, following configuration is available: - $this - ->addRule('type', [ - 'type' => self::TYPE_STRING, - 'description' => 'Algo type.', - 'default' => 'argon2', - 'example' => 'argon2', - ]) - ->addRule('memoryCost', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Memory used to compute hash.', - 'default' => '', - 'example' => 65536, - ]) - ->addRule('timeCost', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Amount of time consumed to compute hash', - 'default' => '', - 'example' => 4, - ]) - ->addRule('threads', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Number of threads used to compute hash.', - 'default' => '', - 'example' => 3, - ]) - ; - } + #[Rule( + description: 'Algo type.', + default: '', + example: 'argon2' + )] + public string $type; - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'AlgoArgon2'; - } + #[Rule( + description: 'Memory used to compute hash.', + default: '', + example: 65536 + )] + public int $memoryCost; - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ALGO_ARGON2; - } + #[Rule( + description: 'Amount of time consumed to compute hash', + default: '', + example: 4 + )] + public int $timeCost; + + #[Rule( + description: 'Number of threads used to compute hash.', + default: '', + example: 3 + )] + public int $threads; } diff --git a/src/Appwrite/Utopia/Response/Model/AlgoBcrypt.php b/src/Appwrite/Utopia/Response/Model/AlgoBcrypt.php index 709dea1a41..3d5ac6f646 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoBcrypt.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoBcrypt.php @@ -3,39 +3,19 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Type; use Appwrite\Utopia\Response\Model; +use Appwrite\Utopia\Response\Rule; +#[Name('AlgoBcrypt')] +#[Type(Response::MODEL_ALGO_BCRYPT)]; class AlgoBcrypt extends Model { - public function __construct() - { - // No options, because this can only be imported, and verifying doesnt require any configuration - $this - ->addRule('type', [ - 'type' => self::TYPE_STRING, - 'description' => 'Algo type.', - 'default' => 'bcrypt', - 'example' => 'bcrypt', - ]); - } - - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'AlgoBcrypt'; - } - - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ALGO_BCRYPT; - } + #[Rule( + description: 'Algo type.', + default: 'bcrypt', + example: 'bcrypt' + )] + public string $type; } diff --git a/src/Appwrite/Utopia/Response/Model/AlgoMd5.php b/src/Appwrite/Utopia/Response/Model/AlgoMd5.php index 509ee70c31..15b62ba7fb 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoMd5.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoMd5.php @@ -3,40 +3,19 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Type; use Appwrite\Utopia\Response\Model; +use Appwrite\Utopia\Response\Rule; +#[Name('AlgoMD5')] +#[Type(Response::MODEL_ALGO_MD5)] class AlgoMd5 extends Model { - public function __construct() - { - // No options, because this can only be imported, and verifying doesnt require any configuration - - $this - ->addRule('type', [ - 'type' => self::TYPE_STRING, - 'description' => 'Algo type.', - 'default' => 'md5', - 'example' => 'md5', - ]); - } - - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'AlgoMD5'; - } - - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ALGO_MD5; - } + #[Rule( + description: 'Algo type.', + default: 'md5', + example: 'md5' + )] + public string $type; } diff --git a/src/Appwrite/Utopia/Response/Model/AlgoPhpass.php b/src/Appwrite/Utopia/Response/Model/AlgoPhpass.php index f16792086e..443b53b0f1 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoPhpass.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoPhpass.php @@ -3,40 +3,19 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Type; use Appwrite\Utopia\Response\Model; +use Appwrite\Utopia\Response\Rule; +#[Name('AlgoPHPass')] +#[Type(Response::MODEL_ALGO_PHPASS)] class AlgoPhpass extends Model { - public function __construct() - { - // No options, because this can only be imported, and verifying doesnt require any configuration - - $this - ->addRule('type', [ - 'type' => self::TYPE_STRING, - 'description' => 'Algo type.', - 'default' => 'phpass', - 'example' => 'phpass', - ]); - } - - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'AlgoPHPass'; - } - - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ALGO_PHPASS; - } + #[Rule( + description: 'Algo type.', + default: 'phpass', + example: 'phpass' + )] + public string $type; } diff --git a/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php b/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php index 4dda297d71..6fb7568c7e 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoScrypt.php @@ -3,63 +3,47 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Type; use Appwrite\Utopia\Response\Model; +use Appwrite\Utopia\Response\Rule; +#[Name('AlgoScrypt')] +#[Type(Response::MODEL_ALGO_SCRYPT)] class AlgoScrypt extends Model { - public function __construct() - { - $this - ->addRule('type', [ - 'type' => self::TYPE_STRING, - 'description' => 'Algo type.', - 'default' => 'scrypt', - 'example' => 'scrypt', - ]) - ->addRule('costCpu', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'CPU complexity of computed hash.', - 'default' => 8, - 'example' => 8, - ]) - ->addRule('costMemory', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Memory complexity of computed hash.', - 'default' => 14, - 'example' => 14, - ]) - ->addRule('costParallel', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Parallelization of computed hash.', - 'default' => 1, - 'example' => 1, - ]) - ->addRule('length', [ - 'type' => self::TYPE_INTEGER, - 'description' => 'Length used to compute hash.', - 'default' => 64, - 'example' => 64, - ]) - ; - } + #[Rule( + description: 'Algo type.', + default: 'scrypt', + example: 'scrypt' + )] + public string $type; - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'AlgoScrypt'; - } + #[Rule( + description: 'CPU complexity of computed hash.', + default: 8, + example: 8 + )] + public int $costCpu; - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ALGO_SCRYPT; - } + #[Rule( + description: 'Memory complexity of computed hash.', + default: 14, + example: 14 + )] + public int $costMemory; + + #[Rule( + description: 'Parallelization of computed hash.', + default: 1, + example: 1 + )] + public int $costParallel; + + #[Rule( + description: 'Length used to compute hash.', + default: 64, + example: 64 + )] + public int $length; } diff --git a/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php b/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php index 40b9df1dad..ca3153fe47 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoScryptModified.php @@ -3,57 +3,40 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Type; use Appwrite\Utopia\Response\Model; +use Appwrite\Utopia\Response\Rule; +#[Name('AlgoScryptModified')] +#[Type(Response::MODEL_ALGO_SCRYPT_MODIFIED)] class AlgoScryptModified extends Model { - public function __construct() - { - $this - ->addRule('type', [ - 'type' => self::TYPE_STRING, - 'description' => 'Algo type.', - 'default' => 'scryptMod', - 'example' => 'scryptMod', - ]) - ->addRule('salt', [ - 'type' => self::TYPE_STRING, - 'description' => 'Salt used to compute hash.', - 'default' => '', - 'example' => 'UxLMreBr6tYyjQ==', - ]) - ->addRule('saltSeparator', [ - 'type' => self::TYPE_STRING, - 'description' => 'Separator used to compute hash.', - 'default' => '', - 'example' => 'Bw==', - ]) - ->addRule('signerKey', [ - 'type' => self::TYPE_STRING, - 'description' => 'Key used to compute hash.', - 'default' => '', - 'example' => 'XyEKE9RcTDeLEsL/RjwPDBv/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==', - ]) - ; - } + #[Rule( + description: 'Algo type.', + default: 'scryptMod', + example: 'scryptMod' + )] + public string $type; - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'AlgoScryptModified'; - } + #[Rule( + description: 'Salt used to compute hash.', + default: '', + example: 'UxLMreBr6tYyjQ==' + )] + public string $salt; - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ALGO_SCRYPT_MODIFIED; - } + #[Rule( + description: 'Separator used to compute hash.', + default: '', + example: 'Bw==' + )] + public string $saltSeparator; + + #[Rule( + description: 'Key used to compute hash.', + default: '', + example: 'XyEKE9RcTDeLEsL/RjwPDBv/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==' + )] + public string $signerKey; } diff --git a/src/Appwrite/Utopia/Response/Model/AlgoSha.php b/src/Appwrite/Utopia/Response/Model/AlgoSha.php index 2a0893adc4..4bebd0ee9d 100644 --- a/src/Appwrite/Utopia/Response/Model/AlgoSha.php +++ b/src/Appwrite/Utopia/Response/Model/AlgoSha.php @@ -3,40 +3,19 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Type; use Appwrite\Utopia\Response\Model; +use Appwrite\Utopia\Response\Rule; +#[Name('AlgoSHA')] +#[Type(Response::MODEL_ALGO_SHA)] class AlgoSha extends Model { - public function __construct() - { - // No options, because this can only be imported, and verifying doesnt require any configuration - - $this - ->addRule('type', [ - 'type' => self::TYPE_STRING, - 'description' => 'Algo type.', - 'default' => 'sha', - 'example' => 'sha', - ]); - } - - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'AlgoSHA'; - } - - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ALGO_SHA; - } + #[Rule( + description: 'Algo type.', + default: 'sha', + example: 'sha' + )] + public string $type; } diff --git a/src/Appwrite/Utopia/Response/Model/Any.php b/src/Appwrite/Utopia/Response/Model/Any.php index 634e0859b9..0fb6ea0d72 100644 --- a/src/Appwrite/Utopia/Response/Model/Any.php +++ b/src/Appwrite/Utopia/Response/Model/Any.php @@ -3,32 +3,16 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Options; +use Appwrite\Utopia\Response\Attribute\Type; use Appwrite\Utopia\Response\Model; +#[Name('Any')] +#[Type(Response::MODEL_ANY)] +#[Options( + any: true +)] class Any extends Model { - /** - * @var bool - */ - protected bool $any = true; - - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'Any'; - } - - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_ANY; - } } diff --git a/src/Appwrite/Utopia/Response/Model/Platform.php b/src/Appwrite/Utopia/Response/Model/Platform.php index 4b8ffb1486..f870a9fa9f 100644 --- a/src/Appwrite/Utopia/Response/Model/Platform.php +++ b/src/Appwrite/Utopia/Response/Model/Platform.php @@ -3,97 +3,78 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; +use Appwrite\Utopia\Response\Attribute\Name; +use Appwrite\Utopia\Response\Attribute\Options; +use Appwrite\Utopia\Response\Attribute\Type; use Appwrite\Utopia\Response\Model; +use Appwrite\Utopia\Response\Rule; +use DateTime; +#[Name('Platform')] +#[Type(Response::MODEL_PLATFORM)] +#[Options(public: false)] class Platform extends Model { - /** - * @var bool - */ - protected bool $public = false; + #[Rule( + description: 'Platform ID.', + default: '', + example: '5e5ea5c16897e' + )] + public string $id; - public function __construct() - { - $this - ->addRule('$id', [ - 'type' => self::TYPE_STRING, - 'description' => 'Platform ID.', - 'default' => '', - 'example' => '5e5ea5c16897e', - ]) - ->addRule('$createdAt', [ - 'type' => self::TYPE_DATETIME, - 'description' => 'Platform creation date in ISO 8601 format.', - 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE, - ]) - ->addRule('$updatedAt', [ - 'type' => self::TYPE_DATETIME, - 'description' => 'Platform update date in ISO 8601 format.', - 'default' => '', - 'example' => self::TYPE_DATETIME_EXAMPLE, - ]) - ->addRule('name', [ - 'type' => self::TYPE_STRING, - 'description' => 'Platform name.', - 'default' => '', - 'example' => 'My Web App', - ]) - ->addRule('type', [ - 'type' => self::TYPE_STRING, - 'description' => 'Platform type. Possible values are: web, flutter-web, flutter-ios, flutter-android, ios, android, and unity.', - 'default' => '', - 'example' => 'web', - ]) - ->addRule('key', [ - 'type' => self::TYPE_STRING, - 'description' => 'Platform Key. iOS bundle ID or Android package name. Empty string for other platforms.', - 'default' => '', - 'example' => 'com.company.appname', - ]) - ->addRule('store', [ - 'type' => self::TYPE_STRING, - 'description' => 'App store or Google Play store ID.', - 'example' => '', - ]) - ->addRule('hostname', [ - 'type' => self::TYPE_STRING, - 'description' => 'Web app hostname. Empty string for other platforms.', - 'default' => '', - 'example' => true, - ]) - ->addRule('httpUser', [ - 'type' => self::TYPE_STRING, - 'description' => 'HTTP basic authentication username.', - 'default' => '', - 'example' => 'username', - ]) - ->addRule('httpPass', [ - 'type' => self::TYPE_STRING, - 'description' => 'HTTP basic authentication password.', - 'default' => '', - 'example' => 'password', - ]) - ; - } + #[Rule( + description: 'Platform creation date in ISO 8601 format.', + default: '', + example: self::TYPE_DATETIME_EXAMPLE + )] + public DateTime $createdAt; - /** - * Get Name - * - * @return string - */ - public function getName(): string - { - return 'Platform'; - } + #[Rule( + description: 'Platform update date in ISO 8601 format.', + default: '', + example: self::TYPE_DATETIME_EXAMPLE + )] + public DateTIme $updatedAt; - /** - * Get Type - * - * @return string - */ - public function getType(): string - { - return Response::MODEL_PLATFORM; - } + #[Rule( + description: 'Platform name.', + default: '', + example: 'My Web App' + )] + public string $name; + + #[Rule( + description: 'Platform description.', + default: '', + example: 'My Web App description' + )] + public string $description; + + #[Rule( + description: 'Platform type. Possible values are: web, flutter-web, flutter-ios, flutter-android, ios, android, and unity.', + default: '', + example: 'web' + )] + public string $type; + + #[Rule( + description: 'Platform Key. iOS bundle ID or Android package name. Empty string for other platforms.', + default: '', + example: 'com.company.appname' + )] + public string $key; + + #[Rule( + description: 'Platform store. Possible values are: google, apple, and microsoft.', + default: '', + example: 'google' + )] + public string $store; + + #[Rule( + description: 'Web app hostname. Empty string for other platforms.', + default: '', + example: 'localhost' + )] + public string $hostname; }