Added new spec parsing lib
This commit is contained in:
parent
b497755454
commit
d9957e13ff
|
@ -1,9 +1,14 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Spec\Spec;
|
||||
use Appwrite\Specification\Format\OpenAPI3;
|
||||
use Appwrite\Specification\Format\Swagger2;
|
||||
use Appwrite\Specification\Specification;
|
||||
use Appwrite\Template\Template;
|
||||
use Utopia\App;
|
||||
use Utopia\View;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Exception;
|
||||
use Utopia\Validator\WhiteList;
|
||||
use Utopia\Validator\Range;
|
||||
|
||||
|
@ -180,30 +185,26 @@ App::get('/error/:code')
|
|||
->setParam('body', $page);
|
||||
}, ['layout']);
|
||||
|
||||
App::get('/open-api-2.json')
|
||||
App::get('/specs/:format')
|
||||
->groups(['web', 'home'])
|
||||
->label('scope', 'public')
|
||||
->label('docs', false)
|
||||
->param('format', 'swagger2', new WhiteList(['swagger2', 'open-api3'], true), 'Spec format.', true)
|
||||
->param('platform', APP_PLATFORM_CLIENT, new WhiteList([APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER, APP_PLATFORM_CONSOLE], true), 'Choose target platform.', true)
|
||||
->param('extensions', 0, new Range(0, 1), 'Show extra data.', true)
|
||||
->param('tests', 0, new Range(0, 1), 'Include only test services.', true)
|
||||
->action(function ($platform, $extensions, $tests, $utopia, $request, $response) {
|
||||
->action(function ($format, $platform, $utopia, $request, $response) {
|
||||
/** @var Utopia\App $utopia */
|
||||
/** @var Utopia\Swoole\Request $request */
|
||||
/** @var Appwrite\Utopia\Response $response */
|
||||
|
||||
$security = [
|
||||
APP_PLATFORM_CLIENT => ['Project' => []],
|
||||
APP_PLATFORM_SERVER => ['Project' => [], 'Key' => []],
|
||||
APP_PLATFORM_CONSOLE => ['Project' => [], 'Key' => []],
|
||||
];
|
||||
|
||||
$platforms = [
|
||||
'client' => APP_PLATFORM_CLIENT,
|
||||
'server' => APP_PLATFORM_SERVER,
|
||||
'all' => APP_PLATFORM_CONSOLE,
|
||||
'console' => APP_PLATFORM_CONSOLE,
|
||||
];
|
||||
|
||||
$routes = [];
|
||||
$models = [];
|
||||
|
||||
$keys = [
|
||||
APP_PLATFORM_CLIENT => [
|
||||
'Project' => [
|
||||
|
@ -267,98 +268,16 @@ App::get('/open-api-2.json')
|
|||
],
|
||||
];
|
||||
|
||||
/*
|
||||
* Specifications (v3.0.0):
|
||||
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
|
||||
*/
|
||||
$output = [
|
||||
'swagger' => '2.0',
|
||||
'info' => [
|
||||
'version' => APP_VERSION_STABLE,
|
||||
'title' => APP_NAME,
|
||||
'description' => 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)',
|
||||
'termsOfService' => 'https://appwrite.io/policy/terms',
|
||||
'contact' => [
|
||||
'name' => 'Appwrite Team',
|
||||
'url' => 'https://appwrite.io/support',
|
||||
'email' => App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM),
|
||||
],
|
||||
'license' => [
|
||||
'name' => 'BSD-3-Clause',
|
||||
'url' => 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE',
|
||||
],
|
||||
],
|
||||
'host' => \parse_url(App::getEnv('_APP_HOME', $request->getHostname()), PHP_URL_HOST),
|
||||
'basePath' => '/v1',
|
||||
'schemes' => ['https'],
|
||||
'consumes' => ['application/json', 'multipart/form-data'],
|
||||
'produces' => ['application/json'],
|
||||
'securityDefinitions' => $keys[$platform],
|
||||
'paths' => [],
|
||||
'definitions' => [
|
||||
// 'Pet' => [
|
||||
// 'required' => ['id', 'name'],
|
||||
// 'properties' => [
|
||||
// 'id' => [
|
||||
// 'type' => 'integer',
|
||||
// 'format' => 'int64',
|
||||
// ],
|
||||
// 'name' => [
|
||||
// 'type' => 'string',
|
||||
// ],
|
||||
// 'tag' => [
|
||||
// 'type' => 'string',
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
// 'Pets' => array(
|
||||
// 'type' => 'array',
|
||||
// 'items' => array(
|
||||
// '$ref' => '#/definitions/Pet',
|
||||
// ),
|
||||
// ),
|
||||
'Error' => array(
|
||||
'required' => array(
|
||||
0 => 'code',
|
||||
1 => 'message',
|
||||
),
|
||||
'properties' => array(
|
||||
'code' => array(
|
||||
'type' => 'integer',
|
||||
'format' => 'int32',
|
||||
),
|
||||
'message' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
'externalDocs' => [
|
||||
'description' => 'Full API docs, specs and tutorials',
|
||||
'url' => $request->getProtocol().'://'.$request->getHostname().'/docs',
|
||||
],
|
||||
$security = [
|
||||
APP_PLATFORM_CLIENT => ['Project' => []],
|
||||
APP_PLATFORM_SERVER => ['Project' => [], 'Key' => []],
|
||||
APP_PLATFORM_CONSOLE => ['Project' => [], 'Key' => []],
|
||||
];
|
||||
|
||||
if ($extensions) {
|
||||
if (isset($output['securityDefinitions']['Project'])) {
|
||||
$output['securityDefinitions']['Project']['extensions'] = ['demo' => '5df5acd0d48c2'];
|
||||
}
|
||||
|
||||
if (isset($output['securityDefinitions']['Key'])) {
|
||||
$output['securityDefinitions']['Key']['extensions'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
|
||||
}
|
||||
|
||||
if (isset($output['securityDefinitions']['Locale'])) {
|
||||
$output['securityDefinitions']['Locale']['extensions'] = ['demo' => 'en'];
|
||||
}
|
||||
|
||||
if (isset($output['securityDefinitions']['Mode'])) {
|
||||
$output['securityDefinitions']['Mode']['extensions'] = ['demo' => ''];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($utopia->getRoutes() as $key => $method) {
|
||||
foreach ($method as $route) { /* @var $route \Utopia\Route */
|
||||
foreach ($method as $route) { /** @var \Utopia\Route $route */
|
||||
var_dump($route->getURL());
|
||||
|
||||
if (!$route->getLabel('docs', true)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -375,184 +294,50 @@ App::get('/open-api-2.json')
|
|||
continue;
|
||||
}
|
||||
|
||||
$url = \str_replace('/v1', '', $route->getURL());
|
||||
$scope = $route->getLabel('scope', '');
|
||||
$hide = $route->getLabel('sdk.hide', false);
|
||||
$consumes = ['application/json'];
|
||||
|
||||
if ($hide) {
|
||||
continue;
|
||||
$routes[] = $route;
|
||||
$model = $response->getModel($route->getLabel('sdk.response.model', 'none'));
|
||||
|
||||
if($model) {
|
||||
$models[$model->getType()] = $model;
|
||||
}
|
||||
|
||||
$desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../'.$route->getLabel('sdk.description', '')) : null;
|
||||
|
||||
$temp = [
|
||||
'summary' => $route->getDesc(),
|
||||
'operationId' => $route->getLabel('sdk.method', \uniqid()),
|
||||
'consumes' => [],
|
||||
'tags' => [$route->getLabel('sdk.namespace', 'default')],
|
||||
'description' => ($desc) ? \file_get_contents($desc) : '',
|
||||
|
||||
// 'responses' => [
|
||||
// 200 => [
|
||||
// 'description' => 'An paged array of pets',
|
||||
// 'schema' => [
|
||||
// '$ref' => '#/definitions/Pet',
|
||||
// ],
|
||||
// ],
|
||||
// ],
|
||||
];
|
||||
|
||||
if ($extensions) {
|
||||
$platformList = $route->getLabel('sdk.platform', []);
|
||||
|
||||
$temp['extensions'] = [
|
||||
'weight' => $route->getOrder(),
|
||||
'cookies' => $route->getLabel('sdk.cookies', false),
|
||||
'type' => $route->getLabel('sdk.methodType', ''),
|
||||
'demo' => 'docs/examples/'. Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($temp['operationId']).'.md',
|
||||
'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' => $platformList,
|
||||
];
|
||||
}
|
||||
|
||||
if ((!empty($scope))) { // && 'public' != $scope
|
||||
$temp['security'][] = $route->getLabel('sdk.security', $security[$platform]);
|
||||
}
|
||||
|
||||
$requestBody = [
|
||||
'content' => [
|
||||
'application/x-www-form-urlencoded' => [
|
||||
'schema' => [
|
||||
'type' => 'object',
|
||||
'properties' => [],
|
||||
],
|
||||
'required' => [],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($route->getParams() as $name => $param) {
|
||||
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $utopia->getResources($param['resources'])) : $param['validator']; /* @var $validator \Utopia\Validator */
|
||||
|
||||
$node = [
|
||||
'name' => $name,
|
||||
'description' => $param['description'],
|
||||
'required' => !$param['optional'],
|
||||
];
|
||||
|
||||
switch ((!empty($validator)) ? \get_class($validator) : '') {
|
||||
case 'Utopia\Validator\Text':
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
|
||||
break;
|
||||
case 'Utopia\Validator\Boolean':
|
||||
$node['type'] = 'boolean';
|
||||
$node['x-example'] = false;
|
||||
break;
|
||||
case 'Appwrite\Database\Validator\UID':
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
|
||||
break;
|
||||
case 'Utopia\Validator\Email':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'email';
|
||||
$node['x-example'] = 'email@example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\URL':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'url';
|
||||
$node['x-example'] = 'https://example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\JSON':
|
||||
case 'Utopia\Validator\Mock':
|
||||
case 'Utopia\Validator\Assoc':
|
||||
$node['type'] = 'object';
|
||||
$node['type'] = 'object';
|
||||
$node['x-example'] = '{}';
|
||||
//$node['format'] = 'json';
|
||||
break;
|
||||
case 'Appwrite\Storage\Validator\File':
|
||||
$consumes = ['multipart/form-data'];
|
||||
$node['type'] = 'file';
|
||||
break;
|
||||
case 'Utopia\Validator\ArrayList':
|
||||
$node['type'] = 'array';
|
||||
$node['collectionFormat'] = 'multi';
|
||||
$node['items'] = [
|
||||
'type' => 'string',
|
||||
];
|
||||
break;
|
||||
case 'Appwrite\Auth\Validator\Password':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'format';
|
||||
$node['x-example'] = 'password';
|
||||
break;
|
||||
case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */
|
||||
$node['type'] = 'integer';
|
||||
$node['format'] = 'int32';
|
||||
$node['x-example'] = $validator->getMin();
|
||||
break;
|
||||
case 'Utopia\Validator\Numeric':
|
||||
$node['type'] = 'integer';
|
||||
$node['format'] = 'int32';
|
||||
break;
|
||||
case 'Utopia\Validator\Length':
|
||||
$node['type'] = 'string';
|
||||
break;
|
||||
case 'Utopia\Validator\Host':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'url';
|
||||
$node['x-example'] = 'https://example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = $validator->getList()[0];
|
||||
break;
|
||||
default:
|
||||
$node['type'] = 'string';
|
||||
break;
|
||||
}
|
||||
|
||||
if ($param['optional'] && !\is_null($param['default'])) { // Param has default value
|
||||
$node['default'] = $param['default'];
|
||||
}
|
||||
|
||||
if (false !== \strpos($url, ':'.$name)) { // Param is in URL path
|
||||
$node['in'] = 'path';
|
||||
$temp['parameters'][] = $node;
|
||||
} elseif ($key == 'GET') { // Param is in query
|
||||
$node['in'] = 'query';
|
||||
$temp['parameters'][] = $node;
|
||||
} else { // Param is in payload
|
||||
$node['in'] = 'formData';
|
||||
$temp['parameters'][] = $node;
|
||||
$requestBody['content']['application/x-www-form-urlencoded']['schema']['properties'][] = $node;
|
||||
|
||||
if (!$param['optional']) {
|
||||
$requestBody['content']['application/x-www-form-urlencoded']['required'][] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
$url = \str_replace(':'.$name, '{'.$name.'}', $url);
|
||||
}
|
||||
|
||||
$temp['consumes'] = $consumes;
|
||||
|
||||
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
|
||||
}
|
||||
}
|
||||
|
||||
/*foreach ($consoleDB->getMocks() as $mock) {
|
||||
var_dump($mock['name']);
|
||||
}*/
|
||||
$models = $response->getModels();
|
||||
|
||||
\ksort($output['paths']);
|
||||
switch ($format) {
|
||||
case 'swagger2':
|
||||
$format = new Swagger2($utopia, $routes, $models, $keys[$platform], $security[$platform]);
|
||||
break;
|
||||
|
||||
case 'open-api3':
|
||||
$format = new OpenAPI3($utopia, $routes, $models, $keys[$platform], $security[$platform]);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Format not found', 404);
|
||||
break;
|
||||
}
|
||||
|
||||
$specs = new Specification($format);
|
||||
|
||||
$format
|
||||
->setParam('name', APP_NAME)
|
||||
->setParam('description', 'Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)')
|
||||
->setParam('endpoint', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/v1')
|
||||
->setParam('version', APP_VERSION_STABLE)
|
||||
->setParam('terms', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/policy/terms')
|
||||
->setParam('support.email', App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM))
|
||||
->setParam('support.url', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/support')
|
||||
->setParam('contact.name', APP_NAME.' Team')
|
||||
->setParam('contact.email', App::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM))
|
||||
->setParam('contact.url', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/support')
|
||||
->setParam('license.name', 'BSD-3-Clause')
|
||||
->setParam('license.url', 'https://raw.githubusercontent.com/appwrite/appwrite/master/LICENSE')
|
||||
->setParam('docs.description', 'Full API docs, specs and tutorials')
|
||||
->setParam('docs.url', App::getEnv('_APP_HOME', $request->getProtocol().'://'.$request->getHostname()).'/docs')
|
||||
;
|
||||
|
||||
$response
|
||||
->json($output);
|
||||
->json($specs->parse());
|
||||
}, ['utopia', 'request', 'response']);
|
124
src/Appwrite/Specification/Format.php
Normal file
124
src/Appwrite/Specification/Format.php
Normal file
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Specification;
|
||||
|
||||
use Utopia\App;
|
||||
use Utopia\Route;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
|
||||
abstract class Format
|
||||
{
|
||||
/**
|
||||
* @var App
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* @var Route[]
|
||||
*/
|
||||
protected $routes;
|
||||
|
||||
/**
|
||||
* @var Model[]
|
||||
*/
|
||||
protected $models;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $keys;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $security;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $params = [
|
||||
'name' => '',
|
||||
'description' => '',
|
||||
'endpoint' => 'https://localhost',
|
||||
'version' => '1.0.0',
|
||||
'terms' => '',
|
||||
'support.email' => '',
|
||||
'support.url' => '',
|
||||
'contact.name' => '',
|
||||
'contact.email' => '',
|
||||
'contact.url' => '',
|
||||
'license.name' => '',
|
||||
'license.url' => '',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param App $app
|
||||
* @param Route[] $routes
|
||||
* @param Model[] $models
|
||||
* @param array $keys
|
||||
* @param array $security
|
||||
*/
|
||||
public function __construct(App $app, array $routes, array $models, array $keys, array $security)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->routes = $routes;
|
||||
$this->models = $models;
|
||||
$this->keys = $keys;
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Name.
|
||||
*
|
||||
* Get format name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getName(): string;
|
||||
|
||||
/**
|
||||
* Parse
|
||||
*
|
||||
* Parses Appwrite App to given format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function parse(): array;
|
||||
|
||||
/**
|
||||
* Set Param.
|
||||
*
|
||||
* Set param value
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setParam(string $key, string $value): self
|
||||
{
|
||||
$this->params[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Param.
|
||||
*
|
||||
* Get param value
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getParam(string $key, string $default = ''): string
|
||||
{
|
||||
if(!isset($this->params[$key])) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->params[$key];
|
||||
}
|
||||
|
||||
}
|
340
src/Appwrite/Specification/Format/OpenAPI3.php
Normal file
340
src/Appwrite/Specification/Format/OpenAPI3.php
Normal file
|
@ -0,0 +1,340 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Specification\Format;
|
||||
|
||||
use Appwrite\Specification\Format;
|
||||
use Appwrite\Template\Template;
|
||||
|
||||
class OpenAPI3 extends Format
|
||||
{
|
||||
/**
|
||||
* Get Name.
|
||||
*
|
||||
* Get format name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName():string
|
||||
{
|
||||
return 'Open API 3';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse
|
||||
*
|
||||
* Parses Appwrite App to given format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parse(): array
|
||||
{
|
||||
/*
|
||||
* Specifications (v3.0.0):
|
||||
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
|
||||
*/
|
||||
$output = [
|
||||
'openapi' => '3.0.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',
|
||||
],
|
||||
],
|
||||
'servers' => [
|
||||
[
|
||||
'url' => $this->getParam('endpoint', ''),
|
||||
],
|
||||
],
|
||||
'paths' => [],
|
||||
'components' => [
|
||||
'schemas' => [],
|
||||
'securitySchemes' => $this->security,
|
||||
],
|
||||
'externalDocs' => [
|
||||
'description' => $this->getParam('docs.description'),
|
||||
'url' => $this->getParam('docs.url'),
|
||||
],
|
||||
];
|
||||
|
||||
if (isset($output['components']['securitySchemes']['Project'])) {
|
||||
$output['components']['securitySchemes']['Project']['x-appwrite'] = ['demo' => '5df5acd0d48c2'];
|
||||
}
|
||||
|
||||
if (isset($output['components']['securitySchemes']['Key'])) {
|
||||
$output['components']['securitySchemes']['Key']['x-appwrite'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
|
||||
}
|
||||
|
||||
if (isset($output['components']['securitySchemes']['Locale'])) {
|
||||
$output['components']['securitySchemes']['Locale']['x-appwrite'] = ['demo' => 'en'];
|
||||
}
|
||||
|
||||
if (isset($output['components']['securitySchemes']['Mode'])) {
|
||||
$output['components']['securitySchemes']['Mode']['x-appwrite'] = ['demo' => ''];
|
||||
}
|
||||
|
||||
foreach ($this->routes as $route) { /* @var $route \Utopia\Route */
|
||||
$url = \str_replace('/v1', '', $route->getURL());
|
||||
$scope = $route->getLabel('scope', '');
|
||||
$hide = $route->getLabel('sdk.hide', false);
|
||||
|
||||
if ($hide) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../'.$route->getLabel('sdk.description', '')) : null;
|
||||
|
||||
$model = $route->getLabel('sdk.response.model', 'none');
|
||||
|
||||
$temp = [
|
||||
|
||||
'summary' => $route->getDesc(),
|
||||
'operationId' => $route->getLabel('sdk.method', \uniqid()),
|
||||
'tags' => [$route->getLabel('sdk.namespace', 'default')],
|
||||
'description' => ($desc) ? \file_get_contents($desc) : '',
|
||||
'responses' => [
|
||||
(string)$route->getLabel('sdk.response.code', '500') => [
|
||||
'description' => '',
|
||||
'content' => [
|
||||
$route->getLabel('sdk.response.type', '') => [
|
||||
'schema' => [
|
||||
'$ref' => '#/components/schemas/'.$model,
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
],
|
||||
'requestBody' => [
|
||||
'content' => [
|
||||
'multipart/form-data' => [
|
||||
'schema' => [
|
||||
'type' => 'object',
|
||||
],
|
||||
],
|
||||
]
|
||||
],
|
||||
'x-appwrite' => [ // Appwrite related metadata
|
||||
'weight' => $route->getOrder(),
|
||||
'cookies' => $route->getLabel('sdk.cookies', false),
|
||||
'type' => $route->getLabel('sdk.methodType', ''),
|
||||
'demo' => 'docs/examples/'. Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($temp['operationId']).'.md',
|
||||
'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' => $route->getLabel('sdk.platform', []),
|
||||
],
|
||||
];
|
||||
|
||||
if ((!empty($scope))) { // && 'public' != $scope
|
||||
$temp['security'][] = $route->getLabel('sdk.security', $this->security);
|
||||
}
|
||||
|
||||
foreach ($route->getParams() as $name => $param) {
|
||||
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['resources'])) : $param['validator']; /* @var $validator \Utopia\Validator */
|
||||
|
||||
$node = [
|
||||
'name' => $name,
|
||||
'description' => $param['description'],
|
||||
'required' => !$param['optional'],
|
||||
];
|
||||
|
||||
switch ((!empty($validator)) ? \get_class($validator) : '') {
|
||||
case 'Utopia\Validator\Text':
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
|
||||
break;
|
||||
case 'Utopia\Validator\Boolean':
|
||||
$node['type'] = 'boolean';
|
||||
$node['x-example'] = false;
|
||||
break;
|
||||
case 'Appwrite\Database\Validator\UID':
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
|
||||
break;
|
||||
case 'Utopia\Validator\Email':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'email';
|
||||
$node['x-example'] = 'email@example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\URL':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'url';
|
||||
$node['x-example'] = 'https://example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\JSON':
|
||||
case 'Utopia\Validator\Mock':
|
||||
case 'Utopia\Validator\Assoc':
|
||||
$node['type'] = 'object';
|
||||
$node['type'] = 'object';
|
||||
$node['x-example'] = '{}';
|
||||
//$node['format'] = 'json';
|
||||
break;
|
||||
case 'Appwrite\Storage\Validator\File':
|
||||
$requestType = 'multipart/form-data';
|
||||
$node['type'] = 'file';
|
||||
break;
|
||||
case 'Utopia\Validator\ArrayList':
|
||||
$node['type'] = 'array';
|
||||
$node['collectionFormat'] = 'multi';
|
||||
$node['items'] = [
|
||||
'type' => 'string',
|
||||
];
|
||||
break;
|
||||
case 'Appwrite\Auth\Validator\Password':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'format';
|
||||
$node['x-example'] = 'password';
|
||||
break;
|
||||
case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */
|
||||
$node['type'] = 'integer';
|
||||
$node['format'] = 'int32';
|
||||
$node['x-example'] = $validator->getMin();
|
||||
break;
|
||||
case 'Utopia\Validator\Numeric':
|
||||
$node['type'] = 'integer';
|
||||
$node['format'] = 'int32';
|
||||
break;
|
||||
case 'Utopia\Validator\Length':
|
||||
$node['type'] = 'string';
|
||||
break;
|
||||
case 'Utopia\Validator\Host':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'url';
|
||||
$node['x-example'] = 'https://example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = $validator->getList()[0];
|
||||
break;
|
||||
default:
|
||||
$node['type'] = 'string';
|
||||
break;
|
||||
}
|
||||
|
||||
if ($param['optional'] && !\is_null($param['default'])) { // Param has default value
|
||||
$node['default'] = $param['default'];
|
||||
}
|
||||
|
||||
if (false !== \strpos($url, ':'.$name)) { // Param is in URL path
|
||||
$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
|
||||
$node['in'] = 'formData';
|
||||
$temp['parameters'][] = $node;
|
||||
$requestBody['content']['application/x-www-form-urlencoded']['schema']['properties'][] = $node;
|
||||
|
||||
if (!$param['optional']) {
|
||||
$requestBody['content']['application/x-www-form-urlencoded']['required'][] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
$url = \str_replace(':'.$name, '{'.$name.'}', $url);
|
||||
}
|
||||
|
||||
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
|
||||
}
|
||||
|
||||
foreach ($this->models as $model) {
|
||||
$required = $model->getRequired();
|
||||
$rules = $model->getRules();
|
||||
|
||||
$output['components']['schemas'][$model->getType()] = [
|
||||
'type' => 'object',
|
||||
'properties' => (empty($rules)) ? new \stdClass : [],
|
||||
];
|
||||
|
||||
if($model->isAny()) {
|
||||
$output['components']['schemas'][$model->getType()]['additionalProperties'] = true;
|
||||
}
|
||||
|
||||
if(!empty($required)) {
|
||||
$output['components']['schemas'][$model->getType()]['required'] = $required;
|
||||
}
|
||||
|
||||
foreach($model->getRules() as $name => $rule) {
|
||||
$type = '';
|
||||
$format = null;
|
||||
$items = null;
|
||||
|
||||
switch ($rule['type']) {
|
||||
case 'string':
|
||||
case 'json':
|
||||
$type = 'string';
|
||||
break;
|
||||
|
||||
case 'integer':
|
||||
$type = 'integer';
|
||||
$format = 'int32';
|
||||
break;
|
||||
|
||||
case 'float':
|
||||
$type = 'number';
|
||||
$format = 'float';
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
$type = 'string';
|
||||
break;
|
||||
|
||||
default:
|
||||
$type = 'object';
|
||||
$rule['type'] = ($rule['type']) ? $rule['type'] : 'none';
|
||||
|
||||
$items = [
|
||||
'type' => $type,
|
||||
'$ref' => '#/components/schemas/'.$rule['type'],
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
if($rule['array']) {
|
||||
$output['components']['schemas'][$model->getType()]['properties'][$name] = [
|
||||
'type' => 'array',
|
||||
'description' => $rule['description'] ?? '',
|
||||
'items' => [
|
||||
'type' => $type,
|
||||
]
|
||||
];
|
||||
|
||||
if($format) {
|
||||
$output['components']['schemas'][$model->getType()]['properties'][$name]['items']['format'] = $format;
|
||||
}
|
||||
|
||||
if($items) {
|
||||
$output['components']['schemas'][$model->getType()]['properties'][$name]['items'] = $items;
|
||||
}
|
||||
} else {
|
||||
$output['components']['schemas'][$model->getType()]['properties'][$name] = [
|
||||
'type' => $type,
|
||||
'description' => $rule['description'] ?? '',
|
||||
];
|
||||
|
||||
if($format) {
|
||||
$output['components']['schemas'][$model->getType()]['properties'][$name]['format'] = $format;
|
||||
}
|
||||
|
||||
if($items) {
|
||||
$output['components']['schemas'][$model->getType()]['properties'][$name]['items'] = $items;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\ksort($output['paths']);
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
393
src/Appwrite/Specification/Format/Swagger2.php
Normal file
393
src/Appwrite/Specification/Format/Swagger2.php
Normal file
|
@ -0,0 +1,393 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Specification\Format;
|
||||
|
||||
use Appwrite\Specification\Format;
|
||||
use Appwrite\Template\Template;
|
||||
|
||||
class Swagger2 extends Format
|
||||
{
|
||||
/**
|
||||
* Get Name.
|
||||
*
|
||||
* Get format name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName():string
|
||||
{
|
||||
return 'Swagger 2';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse
|
||||
*
|
||||
* Parses Appwrite App to given format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parse(): array
|
||||
{
|
||||
/*
|
||||
* Specifications (v3.0.0):
|
||||
* https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md
|
||||
*/
|
||||
$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' => [],
|
||||
'definitions' => [],
|
||||
'externalDocs' => [
|
||||
'description' => $this->getParam('docs.description'),
|
||||
'url' => $this->getParam('docs.url'),
|
||||
],
|
||||
];
|
||||
|
||||
if (isset($output['securityDefinitions']['Project'])) {
|
||||
$output['securityDefinitions']['Project']['x-appwrite'] = ['demo' => '5df5acd0d48c2'];
|
||||
}
|
||||
|
||||
if (isset($output['securityDefinitions']['Key'])) {
|
||||
$output['securityDefinitions']['Key']['x-appwrite'] = ['demo' => '919c2d18fb5d4...a2ae413da83346ad2'];
|
||||
}
|
||||
|
||||
if (isset($output['securityDefinitions']['Locale'])) {
|
||||
$output['securityDefinitions']['Locale']['x-appwrite'] = ['demo' => 'en'];
|
||||
}
|
||||
|
||||
if (isset($output['securityDefinitions']['Mode'])) {
|
||||
$output['securityDefinitions']['Mode']['x-appwrite'] = ['demo' => ''];
|
||||
}
|
||||
|
||||
foreach ($this->routes as $route) { /* @var $route \Utopia\Route */
|
||||
$url = \str_replace('/v1', '', $route->getURL());
|
||||
$scope = $route->getLabel('scope', '');
|
||||
$hide = $route->getLabel('sdk.hide', false);
|
||||
$consumes = [$route->getLabel('sdk.request.type', 'application/json')];
|
||||
|
||||
if ($hide) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$id = $route->getLabel('sdk.method', \uniqid());
|
||||
$desc = (!empty($route->getLabel('sdk.description', ''))) ? \realpath(__DIR__.'/../../../../'.$route->getLabel('sdk.description', '')) : null;
|
||||
$produces = $route->getLabel('sdk.response.type', 'application/json');
|
||||
$model = $route->getLabel('sdk.response.model', 'none');
|
||||
|
||||
$temp = [
|
||||
'summary' => $route->getDesc(),
|
||||
'operationId' => $route->getLabel('sdk.namespace', 'default').ucfirst($id),
|
||||
'consumes' => [],
|
||||
'produces' => [$produces],
|
||||
'tags' => [$route->getLabel('sdk.namespace', 'default')],
|
||||
'description' => ($desc) ? \file_get_contents($desc) : '',
|
||||
'responses' => [],
|
||||
'x-appwrite' => [ // Appwrite related metadata
|
||||
'method' => $route->getLabel('sdk.method', \uniqid()),
|
||||
'weight' => $route->getOrder(),
|
||||
'cookies' => $route->getLabel('sdk.cookies', false),
|
||||
'type' => $route->getLabel('sdk.methodType', ''),
|
||||
'demo' => 'docs/examples/'. Template::fromCamelCaseToDash($route->getLabel('sdk.namespace', 'default')).'/'.Template::fromCamelCaseToDash($id).'.md',
|
||||
'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' => $route->getLabel('sdk.platform', []),
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($this->models as $key => $value) {
|
||||
if($value->getType() === $model) {
|
||||
$model = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($model->isNone()) {
|
||||
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
|
||||
'description' => (in_array($produces, [
|
||||
'image/*',
|
||||
'image/jpeg',
|
||||
'image/gif',
|
||||
'image/png',
|
||||
'image/webp',
|
||||
'image/svg-x',
|
||||
'image/x-icon',
|
||||
'image/bmp',
|
||||
])) ? 'Image' : 'File',
|
||||
'schema' => [
|
||||
'type' => 'file'
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$temp['responses'][(string)$route->getLabel('sdk.response.code', '500')] = [
|
||||
'description' => $model->getName(),
|
||||
'schema' => [
|
||||
'$ref' => '#/definitions/'.$model->getType(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
if ((!empty($scope))) { // && 'public' != $scope
|
||||
$temp['security'][] = $route->getLabel('sdk.security', $this->security);
|
||||
}
|
||||
|
||||
$body = [
|
||||
'name' => 'payload',
|
||||
'in' => 'body',
|
||||
'schema' => [
|
||||
'type' => 'object',
|
||||
'properties' => [],
|
||||
],
|
||||
];
|
||||
|
||||
$bodyRequired = [];
|
||||
|
||||
foreach ($route->getParams() as $name => $param) { // Set params
|
||||
$validator = (\is_callable($param['validator'])) ? call_user_func_array($param['validator'], $this->app->getResources($param['resources'])) : $param['validator']; /* @var $validator \Utopia\Validator */
|
||||
|
||||
$node = [
|
||||
'name' => $name,
|
||||
'description' => $param['description'],
|
||||
'required' => !$param['optional'],
|
||||
];
|
||||
|
||||
switch ((!empty($validator)) ? \get_class($validator) : '') {
|
||||
case 'Utopia\Validator\Text':
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
|
||||
break;
|
||||
case 'Utopia\Validator\Boolean':
|
||||
$node['type'] = 'boolean';
|
||||
$node['x-example'] = false;
|
||||
break;
|
||||
case 'Appwrite\Database\Validator\UID':
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = '['.\strtoupper(Template::fromCamelCaseToSnake($node['name'])).']';
|
||||
break;
|
||||
case 'Utopia\Validator\Email':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'email';
|
||||
$node['x-example'] = 'email@example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\URL':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'url';
|
||||
$node['x-example'] = 'https://example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\JSON':
|
||||
case 'Utopia\Validator\Mock':
|
||||
case 'Utopia\Validator\Assoc':
|
||||
$node['type'] = 'object';
|
||||
$node['type'] = 'object';
|
||||
$node['x-example'] = '{}';
|
||||
//$node['format'] = 'json';
|
||||
break;
|
||||
case 'Appwrite\Storage\Validator\File':
|
||||
$consumes = ['multipart/form-data'];
|
||||
$node['type'] = 'file';
|
||||
break;
|
||||
case 'Utopia\Validator\ArrayList':
|
||||
$node['type'] = 'array';
|
||||
$node['collectionFormat'] = 'multi';
|
||||
$node['items'] = [
|
||||
'type' => 'string',
|
||||
];
|
||||
break;
|
||||
case 'Appwrite\Auth\Validator\Password':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'format';
|
||||
$node['x-example'] = 'password';
|
||||
break;
|
||||
case 'Utopia\Validator\Range': /* @var $validator \Utopia\Validator\Range */
|
||||
$node['type'] = 'integer';
|
||||
$node['format'] = 'int32';
|
||||
$node['x-example'] = $validator->getMin();
|
||||
break;
|
||||
case 'Utopia\Validator\Numeric':
|
||||
$node['type'] = 'integer';
|
||||
$node['format'] = 'int32';
|
||||
break;
|
||||
case 'Utopia\Validator\Length':
|
||||
$node['type'] = 'string';
|
||||
break;
|
||||
case 'Utopia\Validator\Host':
|
||||
$node['type'] = 'string';
|
||||
$node['format'] = 'url';
|
||||
$node['x-example'] = 'https://example.com';
|
||||
break;
|
||||
case 'Utopia\Validator\WhiteList': /* @var $validator \Utopia\Validator\WhiteList */
|
||||
$node['type'] = 'string';
|
||||
$node['x-example'] = $validator->getList()[0];
|
||||
break;
|
||||
default:
|
||||
$node['type'] = 'string';
|
||||
break;
|
||||
}
|
||||
|
||||
if ($param['optional'] && !\is_null($param['default'])) { // Param has default value
|
||||
$node['default'] = $param['default'];
|
||||
}
|
||||
|
||||
if (false !== \strpos($url, ':'.$name)) { // Param is in URL path
|
||||
$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)) {
|
||||
$node['in'] = 'formData';
|
||||
$temp['parameters'][] = $node;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!$param['optional']) {
|
||||
$bodyRequired[] = $name;
|
||||
}
|
||||
|
||||
$body['schema']['properties'][$name] = [
|
||||
'type' => $node['type'],
|
||||
'description' => $node['description'],
|
||||
'default' => $node['default'] ?? null,
|
||||
'x-example' => $node['x-example'] ?? null,
|
||||
];
|
||||
|
||||
if(\array_key_exists('items', $node)) {
|
||||
$body['schema']['properties'][$name]['items'] = $node['items'];
|
||||
}
|
||||
}
|
||||
|
||||
$url = \str_replace(':'.$name, '{'.$name.'}', $url);
|
||||
}
|
||||
|
||||
if(!empty($body['schema']['properties'])) {
|
||||
$temp['parameters'][] = $body;
|
||||
}
|
||||
|
||||
if(!empty($bodyRequired)) {
|
||||
$body['schema']['required'] = $bodyRequired;
|
||||
}
|
||||
|
||||
$temp['consumes'] = $consumes;
|
||||
|
||||
$output['paths'][$url][\strtolower($route->getMethod())] = $temp;
|
||||
}
|
||||
|
||||
foreach ($this->models as $model) {
|
||||
$required = $model->getRequired();
|
||||
$rules = $model->getRules();
|
||||
|
||||
$output['definitions'][$model->getType()] = [
|
||||
'type' => 'object',
|
||||
];
|
||||
|
||||
if(!empty($rules)) {
|
||||
$output['definitions'][$model->getType()]['properties'] = [];
|
||||
}
|
||||
|
||||
if($model->isAny()) {
|
||||
$output['definitions'][$model->getType()]['additionalProperties'] = true;
|
||||
}
|
||||
|
||||
if(!empty($required)) {
|
||||
$output['definitions'][$model->getType()]['required'] = $required;
|
||||
}
|
||||
|
||||
foreach($model->getRules() as $name => $rule) {
|
||||
$type = '';
|
||||
$format = null;
|
||||
$items = null;
|
||||
|
||||
switch ($rule['type']) {
|
||||
case 'string':
|
||||
case 'json':
|
||||
$type = 'string';
|
||||
break;
|
||||
|
||||
case 'integer':
|
||||
$type = 'integer';
|
||||
$format = 'int32';
|
||||
break;
|
||||
|
||||
case 'float':
|
||||
$type = 'number';
|
||||
$format = 'float';
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
$type = 'string';
|
||||
break;
|
||||
|
||||
default:
|
||||
$type = 'object';
|
||||
$rule['type'] = ($rule['type']) ? $rule['type'] : 'none';
|
||||
|
||||
$items = [
|
||||
'type' => $type,
|
||||
'$ref' => '#/definitions/'.$rule['type'],
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
if($rule['array']) {
|
||||
$output['definitions'][$model->getType()]['properties'][$name] = [
|
||||
'type' => 'array',
|
||||
'description' => $rule['description'] ?? '',
|
||||
'items' => [
|
||||
'type' => $type,
|
||||
]
|
||||
];
|
||||
|
||||
if($format) {
|
||||
$output['definitions'][$model->getType()]['properties'][$name]['items']['format'] = $format;
|
||||
}
|
||||
|
||||
if($items) {
|
||||
$output['definitions'][$model->getType()]['properties'][$name]['items'] = $items;
|
||||
}
|
||||
} else {
|
||||
$output['definitions'][$model->getType()]['properties'][$name] = [
|
||||
'type' => $type,
|
||||
'description' => $rule['description'] ?? '',
|
||||
];
|
||||
|
||||
if($format) {
|
||||
$output['definitions'][$model->getType()]['properties'][$name]['format'] = $format;
|
||||
}
|
||||
|
||||
if($items) {
|
||||
$output['definitions'][$model->getType()]['properties'][$name]['items'] = $items;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\ksort($output['paths']);
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
43
src/Appwrite/Specification/Specification.php
Normal file
43
src/Appwrite/Specification/Specification.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Specification;
|
||||
|
||||
class Specification
|
||||
{
|
||||
/**
|
||||
* @var Format
|
||||
*/
|
||||
protected $format;
|
||||
|
||||
/**
|
||||
* @param Format $format
|
||||
*/
|
||||
public function __construct(Format $format)
|
||||
{
|
||||
$this->format = $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Name.
|
||||
*
|
||||
* Get format name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName():string
|
||||
{
|
||||
return $this->format->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse
|
||||
*
|
||||
* Parses Appwrite App to given format
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function parse(): array
|
||||
{
|
||||
return $this->format->parse();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue