1
0
Fork 0
mirror of synced 2024-06-01 18:39:57 +12:00
appwrite/src/Appwrite/Specification/Format/Swagger2.php

649 lines
28 KiB
PHP
Raw Normal View History

2020-11-12 11:02:42 +13:00
<?php
namespace Appwrite\Specification\Format;
use Appwrite\Specification\Format;
use Appwrite\Template\Template;
use Appwrite\Utopia\Response\Model;
2022-12-15 05:04:06 +13:00
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
2021-05-21 19:08:53 +12:00
use Utopia\Validator;
2024-02-02 23:54:34 +13:00
use Utopia\Validator\ArrayList;
2023-03-10 23:06:10 +13:00
use Utopia\Validator\Nullable;
2024-02-02 23:54:34 +13:00
use Utopia\Validator\Range;
2020-11-12 11:02:42 +13:00
class Swagger2 extends Format
{
2022-05-24 02:54:50 +12:00
public function getName(): string
2020-11-12 11:02:42 +13:00
{
return 'Swagger 2';
}
protected function getNestedModels(Model $model, array &$usedModels): void
{
foreach ($model->getRules() as $rule) {
if (!in_array($model->getType(), $usedModels)) {
continue;
}
if (\is_array($rule['type'])) {
foreach ($rule['type'] as $ruleType) {
if (!in_array($ruleType, ['string', 'integer', 'boolean', 'json', 'float'])) {
$usedModels[] = $ruleType;
foreach ($this->models as $m) {
if ($m->getType() === $ruleType) {
$this->getNestedModels($m, $usedModels);
2022-07-26 00:37:29 +12:00
continue;
}
}
}
}
} else {
if (!in_array($rule['type'], ['string', 'integer', 'boolean', 'json', 'float'])) {
$usedModels[] = $rule['type'];
2022-07-26 00:43:17 +12:00
foreach ($this->models as $m) {
if ($m->getType() === $rule['type']) {
$this->getNestedModels($m, $usedModels);
2022-07-26 00:37:29 +12:00
continue;
}
}
}
}
}
}
2020-11-12 11:02:42 +13:00
public function parse(): array
{
/*
* Specifications (v2.0):
* https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md
2020-11-12 11:02:42 +13:00
*/
$output = [
'swagger' => '2.0',
'info' => [
'version' => $this->getParam('version'),
'title' => $this->getParam('name'),
'description' => $this->getParam('description'),
'termsOfService' => $this->getParam('terms'),
'contact' => [
'name' => $this->getParam('contact.name'),
'url' => $this->getParam('contact.url'),
'email' => $this->getParam('contact.email'),
],
'license' => [
'name' => 'BSD-3-Clause',
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
],
],
'host' => \parse_url($this->getParam('endpoint', ''), PHP_URL_HOST),
'basePath' => \parse_url($this->getParam('endpoint', ''), PHP_URL_PATH),
'schemes' => [\parse_url($this->getParam('endpoint', ''), PHP_URL_SCHEME)],
'consumes' => ['application/json', 'multipart/form-data'],
'produces' => ['application/json'],
'securityDefinitions' => $this->keys,
'paths' => [],
'tags' => $this->services,
2020-11-12 11:02:42 +13:00
'definitions' => [],
'externalDocs' => [
'description' => $this->getParam('docs.description'),
'url' => $this->getParam('docs.url'),
],
];
if (isset($output['securityDefinitions']['Project'])) {
$output['securityDefinitions']['Project']['x-appwrite'] = ['demo' => '5df5acd0d48c2'];
}
2020-11-12 11:02:42 +13:00
if (isset($output['securityDefinitions']['Key'])) {
$output['securityDefinitions']['Key']['x-appwrite'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
}
2021-03-29 10:47:17 +13:00
if (isset($output['securityDefinitions']['JWT'])) {
$output['securityDefinitions']['JWT']['x-appwrite'] = ['demo' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ...'];
}
2020-11-12 11:02:42 +13:00
if (isset($output['securityDefinitions']['Locale'])) {
$output['securityDefinitions']['Locale']['x-appwrite'] = ['demo' => 'en'];
}
if (isset($output['securityDefinitions']['Mode'])) {
$output['securityDefinitions']['Mode']['x-appwrite'] = ['demo' => ''];
}
$usedModels = [];
foreach ($this->routes as $route) {
/** @var \Utopia\Route $route */
2021-08-19 17:09:55 +12:00
$url = \str_replace('/v1', '', $route->getPath());
2020-11-12 11:02:42 +13:00
$scope = $route->getLabel('scope', '');
$consumes = [$route->getLabel('sdk.request.type', 'application/json')];
2024-02-25 23:13:28 +13:00
$method = $route->getLabel('sdk.method', \uniqid());
2022-05-24 02:54:50 +12:00
$desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__ . '/../../../../' . $route->getLabel('sdk.description', '')) : null;
2021-02-02 19:02:35 +13:00
$produces = $route->getLabel('sdk.response.type', null);
2021-05-20 01:10:32 +12:00
$model = $route->getLabel('sdk.response.model', 'none');
$routeSecurity = $route->getLabel('sdk.auth', []);
$sdkPlatforms = [];
2021-05-20 01:10:32 +12:00
foreach ($routeSecurity as $value) {
switch ($value) {
case APP_AUTH_TYPE_SESSION:
$sdkPlatforms[] = APP_PLATFORM_CLIENT;
2021-05-20 01:10:32 +12:00
break;
case APP_AUTH_TYPE_KEY:
$sdkPlatforms[] = APP_PLATFORM_SERVER;
2021-05-20 01:10:32 +12:00
break;
case APP_AUTH_TYPE_JWT:
$sdkPlatforms[] = APP_PLATFORM_SERVER;
2021-05-20 01:10:32 +12:00
break;
case APP_AUTH_TYPE_ADMIN:
$sdkPlatforms[] = APP_PLATFORM_CONSOLE;
2021-05-20 01:10:32 +12:00
break;
}
}
2021-05-20 03:29:06 +12:00
2022-05-24 02:54:50 +12:00
if (empty($routeSecurity)) {
2024-02-25 03:38:09 +13:00
$sdkPlatforms[] = APP_PLATFORM_SERVER;
$sdkPlatforms[] = APP_PLATFORM_CLIENT;
2021-05-20 03:29:06 +12:00
}
2024-02-25 02:23:16 +13:00
2020-11-12 11:02:42 +13:00
$temp = [
'summary' => $route->getDesc(),
2024-02-25 23:13:28 +13:00
'operationId' => $route->getLabel('sdk.namespace', 'default') . ucfirst($method),
2020-11-12 11:02:42 +13:00
'consumes' => [],
2021-02-02 19:02:35 +13:00
'produces' => [],
2020-11-12 11:02:42 +13:00
'tags' => [$route->getLabel('sdk.namespace', 'default')],
'description' => ($desc) ? \file_get_contents($desc) : '',
'responses' => [],
'x-appwrite' => [ // Appwrite related metadata
2024-02-25 23:13:28 +13:00
'method' => $method,
2023-08-31 04:36:47 +12:00
'weight' => $route->getOrder(),
2020-11-12 11:02:42 +13:00
'cookies' => $route->getLabel('sdk.cookies', false),
'type' => $route->getLabel('sdk.methodType', ''),
2024-02-25 01:53:47 +13:00
'deprecated' => $route->getLabel('sdk.deprecated', false),
2024-02-25 23:13:28 +13:00
'demo' => Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')) . '/' . Template::fromCamelCaseToDash($method) . '.md',
2020-11-12 11:02:42 +13:00
'edit' => 'https://github.com/appwrite/appwrite/edit/master' . $route->getLabel('sdk.description', ''),
'rate-limit' => $route->getLabel('abuse-limit', 0),
'rate-time' => $route->getLabel('abuse-time', 3600),
'rate-key' => $route->getLabel('abuse-key', 'url:{url},ip:{ip}'),
'scope' => $route->getLabel('scope', ''),
'platforms' => $sdkPlatforms,
2021-01-30 05:13:11 +13:00
'packaging' => $route->getLabel('sdk.packaging', false),
'offline-model' => $route->getLabel('sdk.offline.model', ''),
'offline-key' => $route->getLabel('sdk.offline.key', ''),
'offline-response-key' => $route->getLabel('sdk.offline.response.key', '$id'),
2020-11-12 11:02:42 +13:00
],
];
2022-05-24 02:54:50 +12:00
if ($produces) {
2021-02-02 19:02:35 +13:00
$temp['produces'][] = $produces;
}
foreach ($this->models as $value) {
2022-05-24 02:54:50 +12:00
if (\is_array($model)) {
$model = \array_map(fn ($m) => $m === $value->getType() ? $value : $m, $model);
} else {
2022-05-24 02:54:50 +12:00
if ($value->getType() === $model) {
$model = $value;
break;
}
2020-11-12 11:02:42 +13:00
}
}
2022-05-24 02:54:50 +12:00
if (!(\is_array($model)) && $model->isNone()) {
2020-11-12 11:02:42 +13:00
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => in_array($produces, [
2020-11-12 11:02:42 +13:00
'image/*',
'image/jpeg',
'image/gif',
'image/png',
'image/webp',
'image/svg-x',
'image/x-icon',
'image/bmp',
]) ? 'Image' : 'File',
2020-11-12 11:02:42 +13:00
'schema' => [
'type' => 'file'
],
];
} else {
2022-05-24 02:54:50 +12:00
if (\is_array($model)) {
$modelDescription = \join(', or ', \array_map(fn ($m) => $m->getName(), $model));
// model has multiple possible responses, we will use oneOf
foreach ($model as $m) {
$usedModels[] = $m->getType();
}
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $modelDescription,
2021-10-29 23:55:49 +13:00
'schema' => [
2022-05-24 02:54:50 +12:00
'x-oneOf' => \array_map(function ($m) {
return ['$ref' => '#/definitions/' . $m->getType()];
2021-10-29 23:55:49 +13:00
}, $model)
],
];
} else {
// Response definition using one type
$usedModels[] = $model->getType();
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
'description' => $model->getName(),
2021-10-29 23:55:49 +13:00
'schema' => [
2022-05-24 02:54:50 +12:00
'$ref' => '#/definitions/' . $model->getType(),
],
];
}
2020-11-12 11:02:42 +13:00
}
2022-05-24 02:54:50 +12:00
if (in_array($route->getLabel('sdk.response.code', 500), [204, 301, 302, 308], true)) {
2020-11-12 18:12:40 +13:00
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['description'] = 'No content';
unset($temp['responses'][(string)$route->getLabel('sdk.response.code', '500')]['schema']);
}
2020-11-12 11:02:42 +13:00
if ((!empty($scope))) { // && 'public' != $scope
2021-03-29 10:22:12 +13:00
$securities = ['Project' => []];
2022-05-24 02:54:50 +12:00
foreach ($route->getLabel('sdk.auth', []) as $security) {
if (array_key_exists($security, $this->keys)) {
2021-03-29 10:22:12 +13:00
$securities[$security] = [];
}
}
2021-03-29 10:47:17 +13:00
2021-05-20 02:26:06 +12:00
$temp['x-appwrite']['auth'] = array_slice($securities, 0, $this->authCount);
2021-03-29 10:22:12 +13:00
$temp['security'][] = $securities;
2020-11-12 11:02:42 +13:00
}
2020-11-12 11:02:42 +13:00
$body = [
'name' => 'payload',
'in' => 'body',
'schema' => [
'type' => 'object',
'properties' => [],
],
];
$bodyRequired = [];
$parameters = \array_merge(
$route->getParams(),
$route->getLabel('sdk.parameters', []),
);
foreach ($parameters as $name => $param) { // Set params
2024-02-02 23:54:34 +13:00
/** @var Validator $validator */
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['injections'])) : $param['validator'];
2020-11-12 11:02:42 +13:00
$node = [
'name' => $name,
'description' => $param['description'],
'required' => !$param['optional'],
];
$isNullable = $validator instanceof Nullable;
if ($isNullable) {
/** @var Nullable $validator */
2023-03-10 23:06:10 +13:00
$validator = $validator->getValidator();
}
2022-06-27 20:41:10 +12:00
2020-11-12 11:02:42 +13:00
switch ((!empty($validator)) ? \get_class($validator) : '') {
case 'Utopia\Validator\Text':
2024-02-02 23:54:34 +13:00
case 'Utopia\Database\Validator\UID':
2021-05-21 19:08:53 +12:00
$node['type'] = $validator->getType();
$node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']';
2020-11-12 11:02:42 +13:00
break;
case 'Utopia\Validator\Boolean':
2021-05-21 19:08:53 +12:00
$node['type'] = $validator->getType();
2020-11-12 11:02:42 +13:00
$node['x-example'] = false;
break;
2022-01-19 00:05:04 +13:00
case 'Appwrite\Utopia\Database\Validator\CustomId':
2022-05-24 02:54:50 +12:00
if ($route->getLabel('sdk.methodType', '') === 'upload') {
2022-02-10 23:53:16 +13:00
$node['x-upload-id'] = true;
}
2021-05-21 19:08:53 +12:00
$node['type'] = $validator->getType();
$node['x-example'] = '[' . \strtoupper(Template::fromCamelCaseToSnake($node['name'])) . ']';
2020-11-12 11:02:42 +13:00
break;
2022-07-29 00:38:54 +12:00
case 'Utopia\Database\Validator\DatetimeValidator':
$node['type'] = $validator->getType();
$node['format'] = 'datetime';
$node['x-example'] = Model::TYPE_DATETIME_EXAMPLE;
2022-07-29 00:38:54 +12:00
break;
2021-04-21 18:54:28 +12:00
case 'Appwrite\Network\Validator\Email':
2021-05-21 19:08:53 +12:00
$node['type'] = $validator->getType();
2020-11-12 11:02:42 +13:00
$node['format'] = 'email';
2022-10-04 04:13:04 +13:00
$node['x-example'] = 'email@example.com';
2020-11-12 11:02:42 +13:00
break;
2024-02-02 23:54:34 +13:00
case 'Utopia\Validator\Host':
2023-01-14 04:43:57 +13:00
case 'Utopia\Validator\URL':
2021-05-21 19:08:53 +12:00
$node['type'] = $validator->getType();
2020-11-12 11:02:42 +13:00
$node['format'] = 'url';
$node['x-example'] = 'https://example.com';
break;
2024-02-02 23:54:34 +13:00
case 'Utopia\Validator\ArrayList':
/** @var ArrayList $validator */
$node['type'] = 'array';
$node['collectionFormat'] = 'multi';
$node['items'] = [
'type' => $validator->getValidator()->getType(),
];
break;
2020-11-12 11:02:42 +13:00
case 'Utopia\Validator\JSON':
case 'Utopia\Validator\Mock':
case 'Utopia\Validator\Assoc':
$node['type'] = 'object';
$node['default'] = (empty($param['default'])) ? new \stdClass() : $param['default'];
2020-11-12 11:02:42 +13:00
$node['x-example'] = '{}';
break;
2021-01-22 21:28:33 +13:00
case 'Utopia\Storage\Validator\File':
2020-11-12 11:02:42 +13:00
$consumes = ['multipart/form-data'];
$node['type'] = 'file';
break;
2024-02-02 23:54:34 +13:00
case 'Appwrite\Utopia\Database\Validator\Queries\Attributes':
2022-09-01 04:18:41 +12:00
case 'Appwrite\Utopia\Database\Validator\Queries\Buckets':
case 'Appwrite\Utopia\Database\Validator\Queries\Collections':
case 'Appwrite\Utopia\Database\Validator\Queries\Databases':
case 'Appwrite\Utopia\Database\Validator\Queries\Deployments':
case 'Appwrite\Utopia\Database\Validator\Queries\Executions':
case 'Appwrite\Utopia\Database\Validator\Queries\Files':
case 'Appwrite\Utopia\Database\Validator\Queries\Functions':
2024-02-02 23:54:34 +13:00
case 'Appwrite\Utopia\Database\Validator\Queries\Identities':
case 'Appwrite\Utopia\Database\Validator\Queries\Indexes':
case 'Appwrite\Utopia\Database\Validator\Queries\Installations':
2022-09-01 04:18:41 +12:00
case 'Appwrite\Utopia\Database\Validator\Queries\Memberships':
2024-02-02 23:54:34 +13:00
case 'Appwrite\Utopia\Database\Validator\Queries\Messages':
case 'Appwrite\Utopia\Database\Validator\Queries\Migrations':
2022-09-01 04:18:41 +12:00
case 'Appwrite\Utopia\Database\Validator\Queries\Projects':
2024-02-02 23:54:34 +13:00
case 'Appwrite\Utopia\Database\Validator\Queries\Providers':
case 'Appwrite\Utopia\Database\Validator\Queries\Rules':
case 'Appwrite\Utopia\Database\Validator\Queries\Subscribers':
case 'Appwrite\Utopia\Database\Validator\Queries\Targets':
2022-09-01 04:18:41 +12:00
case 'Appwrite\Utopia\Database\Validator\Queries\Teams':
2024-02-02 23:54:34 +13:00
case 'Appwrite\Utopia\Database\Validator\Queries\Topics':
2022-09-01 04:18:41 +12:00
case 'Appwrite\Utopia\Database\Validator\Queries\Users':
case 'Appwrite\Utopia\Database\Validator\Queries\Variables':
2023-04-27 23:59:05 +12:00
case 'Utopia\Database\Validator\Queries':
2024-02-02 23:54:34 +13:00
case 'Utopia\Database\Validator\Queries\Document':
case 'Utopia\Database\Validator\Queries\Documents':
2020-11-12 11:02:42 +13:00
$node['type'] = 'array';
$node['collectionFormat'] = 'multi';
$node['items'] = [
'type' => 'string',
];
break;
2021-11-02 01:52:08 +13:00
case 'Utopia\Database\Validator\Permissions':
$node['type'] = $validator->getType();
$node['collectionFormat'] = 'multi';
$node['items'] = [
'type' => 'string',
];
2022-08-19 16:04:33 +12:00
$node['x-example'] = '["' . Permission::read(Role::any()) . '"]';
2021-11-02 01:52:08 +13:00
break;
2022-08-15 16:39:30 +12:00
case 'Utopia\Database\Validator\Roles':
$node['type'] = $validator->getType();
$node['collectionFormat'] = 'multi';
$node['items'] = [
'type' => 'string',
];
2022-08-19 16:04:33 +12:00
$node['x-example'] = '["' . Role::any()->toString() . '"]';
2022-08-15 16:39:30 +12:00
break;
2020-11-12 11:02:42 +13:00
case 'Appwrite\Auth\Validator\Password':
2021-05-21 19:08:53 +12:00
$node['type'] = $validator->getType();
2021-05-21 19:31:49 +12:00
$node['format'] = 'password';
2020-11-12 11:02:42 +13:00
$node['x-example'] = 'password';
break;
case 'Appwrite\Auth\Validator\Phone':
$node['type'] = $validator->getType();
$node['format'] = 'phone';
$node['x-example'] = '+12065550100';
break;
case 'Utopia\Validator\Range':
2024-02-02 23:54:34 +13:00
/** @var Range $validator */
2022-05-24 02:54:50 +12:00
$node['type'] = $validator->getType() === Validator::TYPE_FLOAT ? 'number' : $validator->getType();
2021-05-21 19:08:53 +12:00
$node['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float';
2020-11-12 11:02:42 +13:00
$node['x-example'] = $validator->getMin();
break;
case 'Utopia\Validator\Numeric':
case 'Utopia\Validator\Integer':
2021-05-21 19:08:53 +12:00
$node['type'] = $validator->getType();
2020-11-12 11:02:42 +13:00
$node['format'] = 'int32';
break;
case 'Utopia\Validator\FloatValidator':
$node['type'] = 'number';
$node['format'] = 'float';
break;
2020-11-12 11:02:42 +13:00
case 'Utopia\Validator\Length':
2021-05-21 19:08:53 +12:00
$node['type'] = $validator->getType();
2020-11-12 11:02:42 +13:00
break;
case 'Utopia\Validator\WhiteList':
/** @var \Utopia\Validator\WhiteList $validator */
$node['type'] = $validator->getType();
2020-11-12 11:02:42 +13:00
$node['x-example'] = $validator->getList()[0];
2024-02-02 23:54:34 +13:00
//Iterate the blackList. If it matches with the current one, then it is blackListed
2023-08-12 05:20:40 +12:00
$allowed = true;
foreach ($this->enumBlacklist as $blacklist) {
2024-02-25 23:17:37 +13:00
if ($blacklist['namespace'] == $route->getLabel('sdk.namespace', '') && $blacklist['method'] == $method && $blacklist['parameter'] == $name) {
2023-08-12 05:20:40 +12:00
$allowed = false;
break;
}
}
2023-08-12 05:20:40 +12:00
if ($allowed) {
$node['enum'] = $validator->getList();
2024-02-25 23:17:37 +13:00
$node['x-enum-name'] = $this->getEnumName($route->getLabel('sdk.namespace', ''), $method, $name);
$node['x-enum-keys'] = $this->getEnumKeys($route->getLabel('sdk.namespace', ''), $method, $name);
}
2023-08-11 08:55:50 +12:00
if ($validator->getType() === 'integer') {
$node['format'] = 'int32';
}
2020-11-12 11:02:42 +13:00
break;
2024-02-20 20:15:08 +13:00
case 'Appwrite\Utopia\Database\Validator\CompoundUID':
$node['type'] = $validator->getType();
$node['x-example'] = '[ID1:ID2]';
break;
2020-11-12 11:02:42 +13:00
default:
$node['type'] = 'string';
break;
}
if ($param['optional'] && !\is_null($param['default'])) { // Param has default value
$node['default'] = $param['default'];
}
2024-02-02 23:54:34 +13:00
if (\str_contains($url, ':' . $name)) { // Param is in URL path
2020-11-12 11:02:42 +13:00
$node['in'] = 'path';
$temp['parameters'][] = $node;
} elseif ($route->getMethod() == 'GET') { // Param is in query
$node['in'] = 'query';
$temp['parameters'][] = $node;
} else { // Param is in payload
if (\in_array('multipart/form-data', $consumes)) {
2020-11-12 11:02:42 +13:00
$node['in'] = 'formData';
$temp['parameters'][] = $node;
continue;
}
if (!$param['optional']) {
2020-11-12 11:02:42 +13:00
$bodyRequired[] = $name;
}
$body['schema']['properties'][$name] = [
'type' => $node['type'],
'description' => $node['description'],
'default' => $node['default'] ?? null,
'x-example' => $node['x-example'] ?? null,
];
2023-08-11 08:55:50 +12:00
if (isset($node['enum'])) {
/// If the enum flag is Set, add the enum values to the body
$body['schema']['properties'][$name]['enum'] = $node['enum'];
$body['schema']['properties'][$name]['x-enum-name'] = $node['x-enum-name'] ?? null;
$body['schema']['properties'][$name]['x-enum-keys'] = $node['x-enum-keys'] ?? null;
}
if ($node['x-global'] ?? false) {
$body['schema']['properties'][$name]['x-global'] = true;
}
if ($isNullable) {
$body['schema']['properties'][$name]['x-nullable'] = true;
}
2022-05-24 02:54:50 +12:00
if (\array_key_exists('items', $node)) {
2020-11-12 11:02:42 +13:00
$body['schema']['properties'][$name]['items'] = $node['items'];
}
}
2022-05-24 02:54:50 +12:00
$url = \str_replace(':' . $name, '{' . $name . '}', $url);
2020-11-12 11:02:42 +13:00
}
2022-05-24 02:54:50 +12:00
if (!empty($bodyRequired)) {
2020-11-12 11:02:42 +13:00
$body['schema']['required'] = $bodyRequired;
}
2022-05-24 02:54:50 +12:00
if (!empty($body['schema']['properties'])) {
2020-11-15 00:52:07 +13:00
$temp['parameters'][] = $body;
}
2020-11-12 11:02:42 +13:00
$temp['consumes'] = $consumes;
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
}
2020-11-12 11:02:42 +13:00
foreach ($this->models as $model) {
$this->getNestedModels($model, $usedModels);
2021-04-08 21:24:41 +12:00
}
2020-11-12 11:02:42 +13:00
foreach ($this->models as $model) {
if (!in_array($model->getType(), $usedModels)) {
continue;
}
2020-11-12 11:02:42 +13:00
$required = $model->getRequired();
$rules = $model->getRules();
$output['definitions'][$model->getType()] = [
2020-11-14 09:38:47 +13:00
'description' => $model->getName(),
2020-11-12 11:02:42 +13:00
'type' => 'object',
];
2022-05-24 02:54:50 +12:00
if (!empty($rules)) {
2020-11-12 11:02:42 +13:00
$output['definitions'][$model->getType()]['properties'] = [];
}
2022-05-24 02:54:50 +12:00
if ($model->isAny()) {
2020-11-12 11:02:42 +13:00
$output['definitions'][$model->getType()]['additionalProperties'] = true;
}
2022-05-24 02:54:50 +12:00
if (!empty($required)) {
2020-11-12 11:02:42 +13:00
$output['definitions'][$model->getType()]['required'] = $required;
}
2022-05-24 02:54:50 +12:00
foreach ($model->getRules() as $name => $rule) {
2020-11-12 11:02:42 +13:00
$type = '';
$format = null;
$items = null;
switch ($rule['type']) {
case 'string':
2022-07-29 00:38:54 +12:00
case 'datetime':
2020-11-12 11:02:42 +13:00
$type = 'string';
break;
case 'json':
$type = 'object';
break;
2020-11-12 11:02:42 +13:00
case 'integer':
$type = 'integer';
$format = 'int32';
break;
case 'float':
$type = 'number';
$format = 'float';
break;
2021-09-22 00:25:41 +12:00
case 'double':
$type = 'number';
$format = 'double';
break;
2020-11-12 11:02:42 +13:00
case 'boolean':
2020-11-14 12:28:01 +13:00
$type = 'boolean';
2020-11-12 11:02:42 +13:00
break;
2020-11-12 11:02:42 +13:00
default:
$type = 'object';
$rule['type'] = ($rule['type']) ?: 'none';
2020-11-12 11:02:42 +13:00
2022-05-24 02:54:50 +12:00
if (\is_array($rule['type'])) {
if ($rule['array']) {
$items = [
'x-anyOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/' . $type], $rule['type'])
];
} else {
$items = [
'x-oneOf' => \array_map(fn ($type) => ['$ref' => '#/definitions/' . $type], $rule['type'])
];
}
} else {
$items = [
2021-09-22 00:19:25 +12:00
'type' => $type,
2022-05-24 02:54:50 +12:00
'$ref' => '#/definitions/' . $rule['type'],
];
}
2020-11-12 11:02:42 +13:00
break;
}
2022-03-02 16:22:48 +13:00
if ($rule['type'] == 'json') {
$output['definitions'][$model->getType()]['properties'][$name] = [
'type' => $type,
'additionalProperties' => true,
'description' => $rule['description'] ?? '',
'x-example' => $rule['example'] ?? null,
];
continue;
}
2022-05-24 02:54:50 +12:00
if ($rule['array']) {
2020-11-12 11:02:42 +13:00
$output['definitions'][$model->getType()]['properties'][$name] = [
'type' => 'array',
'description' => $rule['description'] ?? '',
'items' => [
'type' => $type,
2021-02-01 12:07:11 +13:00
],
'x-example' => $rule['example'] ?? null,
2020-11-12 11:02:42 +13:00
];
2022-05-24 02:54:50 +12:00
if ($format) {
2020-11-12 11:02:42 +13:00
$output['definitions'][$model->getType()]['properties'][$name]['items']['format'] = $format;
}
} else {
$output['definitions'][$model->getType()]['properties'][$name] = [
'type' => $type,
'description' => $rule['description'] ?? '',
2020-11-14 09:38:47 +13:00
'x-example' => $rule['example'] ?? null,
2020-11-12 11:02:42 +13:00
];
2022-05-24 02:54:50 +12:00
if ($format) {
2020-11-12 11:02:42 +13:00
$output['definitions'][$model->getType()]['properties'][$name]['format'] = $format;
}
}
2022-05-24 02:54:50 +12:00
if ($items) {
$output['definitions'][$model->getType()]['properties'][$name]['items'] = $items;
2020-11-12 11:02:42 +13:00
}
if (!in_array($name, $required)) {
$output['definitions'][$model->getType()]['properties'][$name]['x-nullable'] = true;
}
2020-11-12 11:02:42 +13:00
}
}
\ksort($output['paths']);
return $output;
}
}