OpenAPI Gen: handle Object to Schema transformation correctly
All the basic mechanisms should now be in place to clean up the API
This commit is contained in:
parent
53c2a557e0
commit
dd7472d3f8
|
@ -3,6 +3,8 @@
|
|||
namespace dokuwiki\Remote;
|
||||
|
||||
|
||||
use dokuwiki\Remote\OpenApiDoc\DocBlockMethod;
|
||||
|
||||
class ApiCall
|
||||
{
|
||||
/** @var callable The method to be called for this endpoint */
|
||||
|
@ -11,29 +13,13 @@ class ApiCall
|
|||
/** @var bool Whether this call can be called without authentication */
|
||||
protected bool $isPublic = false;
|
||||
|
||||
/** @var array Metadata on the accepted parameters */
|
||||
protected array $args = [];
|
||||
|
||||
/** @var array Metadata on the return value */
|
||||
protected array $return = [
|
||||
'type' => 'string',
|
||||
'description' => '',
|
||||
];
|
||||
|
||||
/** @var string The summary of the method */
|
||||
protected string $summary = '';
|
||||
|
||||
/** @var string The description of the method */
|
||||
protected string $description = '';
|
||||
|
||||
/** @var array[] The parsed tags */
|
||||
protected $tags;
|
||||
/** @var DocBlockMethod The meta data of this call as parsed from its doc block */
|
||||
protected $docs;
|
||||
|
||||
/**
|
||||
* Make the given method available as an API call
|
||||
*
|
||||
* @param string|array $method Either [object,'method'] or 'function'
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function __construct($method)
|
||||
{
|
||||
|
@ -42,7 +28,6 @@ class ApiCall
|
|||
}
|
||||
|
||||
$this->method = $method;
|
||||
$this->parseData();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,6 +46,32 @@ class ApiCall
|
|||
return call_user_func_array($this->method, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the method documentation
|
||||
*
|
||||
* This lazy loads the docs only when needed
|
||||
*
|
||||
* @return DocBlockMethod
|
||||
*/
|
||||
public function getDocs()
|
||||
{
|
||||
if ($this->docs === null) {
|
||||
try {
|
||||
if (is_array($this->method)) {
|
||||
$reflect = new \ReflectionMethod($this->method[0], $this->method[1]);
|
||||
} else {
|
||||
$reflect = new \ReflectionFunction($this->method);
|
||||
}
|
||||
$this->docs = new DocBlockMethod($reflect);
|
||||
} catch (\ReflectionException $e) {
|
||||
throw new \RuntimeException('Failed to parse API method documentation', 0, $e);
|
||||
}
|
||||
|
||||
}
|
||||
return $this->docs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -85,41 +96,7 @@ class ApiCall
|
|||
*/
|
||||
public function getArgs(): array
|
||||
{
|
||||
return $this->args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the arguments to the given ones
|
||||
*
|
||||
* @param string[] $args
|
||||
* @return $this
|
||||
*/
|
||||
public function limitArgs($args): self
|
||||
{
|
||||
foreach ($args as $arg) {
|
||||
if (!isset($this->args[$arg])) {
|
||||
throw new \InvalidArgumentException("Unknown argument $arg");
|
||||
}
|
||||
}
|
||||
$this->args = array_intersect_key($this->args, array_flip($args));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the description for an argument
|
||||
*
|
||||
* @param string $arg
|
||||
* @param string $description
|
||||
* @return $this
|
||||
*/
|
||||
public function setArgDescription(string $arg, string $description): self
|
||||
{
|
||||
if (!isset($this->args[$arg])) {
|
||||
throw new \InvalidArgumentException('Unknown argument');
|
||||
}
|
||||
$this->args[$arg]['description'] = $description;
|
||||
return $this;
|
||||
return $this->getDocs()->getParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,19 +104,7 @@ class ApiCall
|
|||
*/
|
||||
public function getReturn(): array
|
||||
{
|
||||
return $this->return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the description for the return value
|
||||
*
|
||||
* @param string $description
|
||||
* @return $this
|
||||
*/
|
||||
public function setReturnDescription(string $description): self
|
||||
{
|
||||
$this->return['description'] = $description;
|
||||
return $this;
|
||||
return $this->getDocs()->getReturn();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,17 +112,7 @@ class ApiCall
|
|||
*/
|
||||
public function getSummary(): string
|
||||
{
|
||||
return $this->summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $summary
|
||||
* @return $this
|
||||
*/
|
||||
public function setSummary(string $summary): self
|
||||
{
|
||||
$this->summary = $summary;
|
||||
return $this;
|
||||
return $this->getDocs()->getSummary();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -165,203 +120,7 @@ class ApiCall
|
|||
*/
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
* @return $this
|
||||
*/
|
||||
public function setDescription(string $description): self
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the docblock tags that have not been processed specially
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
public function getTags()
|
||||
{
|
||||
return $this->tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any data that is available in the given docblock tag
|
||||
*
|
||||
* @param string $tag
|
||||
* @return string[] returns an empty array if no such tags exists
|
||||
*/
|
||||
public function getTag($tag)
|
||||
{
|
||||
if(isset($this->tags[$tag])) {
|
||||
return $this->tags[$tag];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in the metadata
|
||||
*
|
||||
* This uses Reflection to inspect the method signature and doc block
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function parseData()
|
||||
{
|
||||
if (is_array($this->method)) {
|
||||
$reflect = new \ReflectionMethod($this->method[0], $this->method[1]);
|
||||
} else {
|
||||
$reflect = new \ReflectionFunction($this->method);
|
||||
}
|
||||
|
||||
$docInfo = $this->parseDocBlock($reflect->getDocComment());
|
||||
$this->summary = $docInfo['summary'];
|
||||
$this->description = $docInfo['description'];
|
||||
$this->tags = $docInfo['tags'];
|
||||
|
||||
foreach ($reflect->getParameters() as $parameter) {
|
||||
$name = $parameter->name;
|
||||
$realType = $parameter->getType();
|
||||
if ($realType) {
|
||||
$type = $realType->getName();
|
||||
} elseif (isset($docInfo['args'][$name]['type'])) {
|
||||
$type = $docInfo['args'][$name]['type'];
|
||||
} else {
|
||||
$type = 'string';
|
||||
}
|
||||
|
||||
if (isset($docInfo['args'][$name]['description'])) {
|
||||
$description = $docInfo['args'][$name]['description'];
|
||||
} else {
|
||||
$description = '';
|
||||
}
|
||||
|
||||
$this->args[$name] = [
|
||||
'type' => $type,
|
||||
'description' => trim($description),
|
||||
];
|
||||
}
|
||||
|
||||
$returnType = $reflect->getReturnType();
|
||||
if ($returnType) {
|
||||
$this->return['type'] = $returnType->getName();
|
||||
} elseif (isset($docInfo['return']['type'])) {
|
||||
$this->return['type'] = $docInfo['return']['type'];
|
||||
} else {
|
||||
$this->return['type'] = 'string';
|
||||
}
|
||||
|
||||
if (isset($docInfo['return']['response'])) {
|
||||
$this->return['response'] = $docInfo['return']['response'];
|
||||
}
|
||||
|
||||
if (isset($docInfo['return']['description'])) {
|
||||
$this->return['description'] = $docInfo['return']['description'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a doc block
|
||||
*
|
||||
* @param string $doc
|
||||
* @return array
|
||||
*/
|
||||
protected function parseDocBlock($doc)
|
||||
{
|
||||
// strip asterisks and leading spaces
|
||||
$doc = preg_replace(
|
||||
['/^[ \t]*\/\*+[ \t]*/m', '/[ \t]*\*+[ \t]*/m', '/\*+\/\s*$/m', '/\s*\/\s*$/m'],
|
||||
['', '', '', ''],
|
||||
$doc
|
||||
);
|
||||
|
||||
$doc = trim($doc);
|
||||
|
||||
// get all tags
|
||||
$tags = [];
|
||||
if (preg_match_all('/^@(\w+)\s+(.*)$/m', $doc, $matches, PREG_SET_ORDER)) {
|
||||
foreach ($matches as $match) {
|
||||
$tags[$match[1]][] = trim($match[2]);
|
||||
}
|
||||
}
|
||||
$params = $this->extractDocTags($tags);
|
||||
|
||||
// strip the tags from the doc
|
||||
$doc = preg_replace('/^@(\w+)\s+(.*)$/m', '', $doc);
|
||||
|
||||
[$summary, $description] = sexplode("\n\n", $doc, 2, '');
|
||||
return array_merge(
|
||||
[
|
||||
'summary' => trim($summary),
|
||||
'description' => trim($description),
|
||||
'tags' => $tags,
|
||||
],
|
||||
$params
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the param and return tags
|
||||
*
|
||||
* @param array $tags
|
||||
* @return array
|
||||
*/
|
||||
protected function extractDocTags(&$tags)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
if (isset($tags['param'])) {
|
||||
foreach ($tags['param'] as $param) {
|
||||
[$type, $name, $description] = array_map('trim', sexplode(' ', $param, 3, ''));
|
||||
if ($name[0] !== '$') continue;
|
||||
$name = substr($name, 1);
|
||||
|
||||
$result['args'][$name] = [
|
||||
'type' => $this->cleanTypeHint($type),
|
||||
'description' => $description,
|
||||
];
|
||||
}
|
||||
unset($tags['param']);
|
||||
}
|
||||
|
||||
if (isset($tags['return'])) {
|
||||
$return = $tags['return'][0];
|
||||
[$type, $description] = array_map('trim', sexplode(' ', $return, 2, ''));
|
||||
$result['return'] = [
|
||||
'type' => $this->cleanTypeHint($type),
|
||||
'response' => $type, // uncleaned
|
||||
'description' => $description
|
||||
];
|
||||
unset($tags['return']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the given type hint against the valid options for the remote API
|
||||
*
|
||||
* @param string $hint
|
||||
* @return string
|
||||
*/
|
||||
protected function cleanTypeHint($hint)
|
||||
{
|
||||
$types = explode('|', $hint);
|
||||
foreach ($types as $t) {
|
||||
if (str_ends_with($t, '[]')) {
|
||||
return 'array';
|
||||
}
|
||||
if ($t === 'boolean' || $t === 'true' || $t === 'false') {
|
||||
return 'bool';
|
||||
}
|
||||
if (in_array($t, ['array', 'string', 'int', 'double', 'bool', 'null', 'date', 'file'])) {
|
||||
return $t;
|
||||
}
|
||||
}
|
||||
return 'string';
|
||||
return $this->getDocs()->getDescription();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -375,7 +134,7 @@ class ApiCall
|
|||
{
|
||||
$args = [];
|
||||
|
||||
foreach (array_keys($this->args) as $arg) {
|
||||
foreach (array_keys($this->docs->getParameters()) as $arg) {
|
||||
if (isset($params[$arg])) {
|
||||
$args[] = $params[$arg];
|
||||
} else {
|
||||
|
|
|
@ -52,21 +52,21 @@ class ApiCore
|
|||
'dokuwiki.appendPage' => new ApiCall([$this, 'appendPage']),
|
||||
'dokuwiki.createUser' => new ApiCall([$this, 'createUser']),
|
||||
'dokuwiki.deleteUsers' => new ApiCall([$this, 'deleteUsers']),
|
||||
'wiki.getPage' => (new ApiCall([$this, 'rawPage']))
|
||||
->limitArgs(['page']),
|
||||
'wiki.getPageVersion' => (new ApiCall([$this, 'rawPage']))
|
||||
->setSummary('Get a specific revision of a wiki page'),
|
||||
'wiki.getPageHTML' => (new ApiCall([$this, 'htmlPage']))
|
||||
->limitArgs(['page']),
|
||||
'wiki.getPageHTMLVersion' => (new ApiCall([$this, 'htmlPage']))
|
||||
->setSummary('Get the HTML for a specific revision of a wiki page'),
|
||||
// 'wiki.getPage' => (new ApiCall([$this, 'rawPage']))
|
||||
// ->limitArgs(['page']),
|
||||
// 'wiki.getPageVersion' => (new ApiCall([$this, 'rawPage']))
|
||||
// ->setSummary('Get a specific revision of a wiki page'),
|
||||
// 'wiki.getPageHTML' => (new ApiCall([$this, 'htmlPage']))
|
||||
// ->limitArgs(['page']),
|
||||
// 'wiki.getPageHTMLVersion' => (new ApiCall([$this, 'htmlPage']))
|
||||
// ->setSummary('Get the HTML for a specific revision of a wiki page'),
|
||||
'wiki.getAllPages' => new ApiCall([$this, 'listPages']),
|
||||
'wiki.getAttachments' => new ApiCall([$this, 'listAttachments']),
|
||||
'wiki.getBackLinks' => new ApiCall([$this, 'listBackLinks']),
|
||||
'wiki.getPageInfo' => (new ApiCall([$this, 'pageInfo']))
|
||||
->limitArgs(['page']),
|
||||
'wiki.getPageInfoVersion' => (new ApiCall([$this, 'pageInfo']))
|
||||
->setSummary('Get some basic data about a specific revison of a wiki page'),
|
||||
// 'wiki.getPageInfo' => (new ApiCall([$this, 'pageInfo']))
|
||||
// ->limitArgs(['page']),
|
||||
// 'wiki.getPageInfoVersion' => (new ApiCall([$this, 'pageInfo']))
|
||||
// ->setSummary('Get some basic data about a specific revison of a wiki page'),
|
||||
'wiki.getPageVersions' => new ApiCall([$this, 'pageVersions']),
|
||||
'wiki.putPage' => new ApiCall([$this, 'putPage']),
|
||||
'wiki.listLinks' => new ApiCall([$this, 'listLinks']),
|
||||
|
@ -198,7 +198,7 @@ class ApiCore
|
|||
*
|
||||
* This uses the search index and only returns pages that have been indexed already
|
||||
*
|
||||
* @return array[] A list of all pages with id, perms, size, lastModified
|
||||
* @return Page[] A list of all pages with id, perms, size, lastModified
|
||||
*/
|
||||
public function listPages()
|
||||
{
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
namespace dokuwiki\Remote;
|
||||
|
||||
use dokuwiki\Remote\OpenApiDoc\DocBlockClass;
|
||||
use dokuwiki\Remote\OpenApiDoc\Type;
|
||||
use dokuwiki\Utf8\PhpString;
|
||||
|
||||
class OpenAPIGenerator
|
||||
|
@ -78,45 +80,10 @@ class OpenAPIGenerator
|
|||
}
|
||||
}
|
||||
|
||||
protected function addComponents()
|
||||
{
|
||||
$schemas = [];
|
||||
|
||||
$files = glob(DOKU_INC . 'inc/Remote/Response/*.php');
|
||||
foreach ($files as $file) {
|
||||
$name = basename($file, '.php');
|
||||
$class = 'dokuwiki\\Remote\\Response\\' . $name;
|
||||
$reflection = new \ReflectionClass($class);
|
||||
if($reflection->isAbstract()) continue;
|
||||
|
||||
$classDoc = new OpenApiDoc\DocBlockClass($reflection);
|
||||
|
||||
|
||||
$schemas[$name] = [
|
||||
'type' => 'object',
|
||||
'summary' => $classDoc->getSummary(),
|
||||
'description' => $classDoc->getDescription(),
|
||||
'properties' => [],
|
||||
];
|
||||
|
||||
foreach ($classDoc->getPropertyDocs() as $property => $doc) {
|
||||
$schemas[$name]['properties'][$property] = [
|
||||
'type' => $this->fixTypes($doc->getTag('type')),
|
||||
'description' => $doc->getSummary(),
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected function getMethodDefinition(string $method, ApiCall $call)
|
||||
{
|
||||
$retType = $this->fixTypes($call->getReturn()['type']);
|
||||
$retExample = $this->generateExample('result', $retType);
|
||||
|
||||
$description = $call->getDescription();
|
||||
$links = $call->getTag('link');
|
||||
$links = $call->getDocs()->getTag('link');
|
||||
if ($links) {
|
||||
$description .= "\n\n**See also:**";
|
||||
foreach ($links as $link) {
|
||||
|
@ -124,6 +91,15 @@ class OpenAPIGenerator
|
|||
}
|
||||
}
|
||||
|
||||
$retType = $call->getReturn()['type'];
|
||||
$result = array_merge(
|
||||
[
|
||||
'description' => $call->getReturn()['description'],
|
||||
'examples' => [$this->generateExample('result', $retType->getOpenApiType())],
|
||||
],
|
||||
$this->typeToSchema($retType)
|
||||
);
|
||||
|
||||
return [
|
||||
'operationId' => $method,
|
||||
'summary' => $call->getSummary(),
|
||||
|
@ -142,11 +118,7 @@ class OpenAPIGenerator
|
|||
'schema' => [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'result' => [
|
||||
'type' => $retType,
|
||||
'description' => $call->getReturn()['description'],
|
||||
'examples' => [$retExample],
|
||||
],
|
||||
'result' => $result,
|
||||
'error' => [
|
||||
'type' => 'object',
|
||||
'description' => 'Error object in case of an error',
|
||||
|
@ -189,37 +161,18 @@ class OpenAPIGenerator
|
|||
];
|
||||
|
||||
foreach ($args as $name => $info) {
|
||||
$type = $this->fixTypes($info['type']);
|
||||
$example = $this->generateExample($name, $type);
|
||||
$props[$name] = [
|
||||
'type' => $type,
|
||||
'description' => $info['description'],
|
||||
'examples' => [$example],
|
||||
];
|
||||
$example = $this->generateExample($name, $info['type']->getOpenApiType());
|
||||
$props[$name] = array_merge(
|
||||
[
|
||||
'description' => $info['description'],
|
||||
'examples' => [$example],
|
||||
],
|
||||
$this->typeToSchema($info['type'])
|
||||
);
|
||||
}
|
||||
return $schema;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected function fixTypes($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'int':
|
||||
$type = 'integer';
|
||||
break;
|
||||
case 'bool':
|
||||
$type = 'boolean';
|
||||
break;
|
||||
case 'file':
|
||||
$type = 'string';
|
||||
break;
|
||||
|
||||
}
|
||||
return $type;
|
||||
}
|
||||
|
||||
protected function generateExample($name, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
|
@ -257,4 +210,46 @@ class OpenAPIGenerator
|
|||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the OpenAPI schema for the given type
|
||||
*
|
||||
* @param Type $type
|
||||
* @return array
|
||||
* @todo add example generation here
|
||||
*/
|
||||
public function typeToSchema(Type $type)
|
||||
{
|
||||
$schema = [
|
||||
'type' => $type->getOpenApiType(),
|
||||
];
|
||||
|
||||
// if a sub type is known, define the items
|
||||
if($schema['type'] === 'array' && $type->getSubType()) {
|
||||
$schema['items'] = $this->typeToSchema($type->getSubType());
|
||||
}
|
||||
|
||||
// if this is an object, define the properties
|
||||
if($schema['type'] === 'object') {
|
||||
try {
|
||||
$baseType = $type->getBaseType();
|
||||
$doc = new DocBlockClass(new \ReflectionClass($baseType));
|
||||
$schema['properties'] = [];
|
||||
foreach ($doc->getPropertyDocs() as $property => $propertyDoc) {
|
||||
$schema['properties'][$property] = array_merge(
|
||||
[
|
||||
'description' => $propertyDoc->getSummary(),
|
||||
],
|
||||
$this->typeToSchema($propertyDoc->getType())
|
||||
);
|
||||
}
|
||||
} catch (\ReflectionException $e) {
|
||||
// The class is not available, so we cannot generate a schema
|
||||
}
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace dokuwiki\Remote\OpenApiDoc;
|
||||
|
||||
use ReflectionFunction;
|
||||
use ReflectionMethod;
|
||||
|
||||
class DocBlockMethod extends DocBlock
|
||||
|
@ -12,16 +13,42 @@ class DocBlockMethod extends DocBlock
|
|||
*
|
||||
* The docblock can be of a method, class or property.
|
||||
*
|
||||
* @param ReflectionMethod $reflector
|
||||
* @param ReflectionMethod|ReflectionFunction $reflector
|
||||
*/
|
||||
public function __construct(ReflectionMethod $reflector)
|
||||
public function __construct($reflector)
|
||||
{
|
||||
parent::__construct($reflector);
|
||||
$this->refineParam();
|
||||
$this->refineReturn();
|
||||
}
|
||||
|
||||
protected function getContext()
|
||||
{
|
||||
if($this->reflector instanceof ReflectionFunction) {
|
||||
return null;
|
||||
}
|
||||
return parent::getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to access the method parameters
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters()
|
||||
{
|
||||
return $this->getTag('param');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to access the method return
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getReturn()
|
||||
{
|
||||
return $this->getTag('return');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the param tag into its components
|
||||
|
@ -77,7 +104,7 @@ class DocBlockMethod extends DocBlock
|
|||
// refine from doc tag
|
||||
foreach ($this->tags['return'] ?? [] as $return) {
|
||||
[$type, $description] = array_map('trim', sexplode(' ', $return, 2, ''));
|
||||
$result['type'] = new Type($type);
|
||||
$result['type'] = new Type($type, $this->getContext());
|
||||
$result['description'] = $description;
|
||||
|
||||
}
|
||||
|
|
|
@ -28,13 +28,16 @@ class Type
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a primitive PHP type
|
||||
* Return the base type
|
||||
*
|
||||
* This is the type this variable is. Eg. a string[] is an array.
|
||||
*
|
||||
* @param string $typehint
|
||||
* @return string
|
||||
*/
|
||||
protected function toPrimitiveType($typehint)
|
||||
public function getBaseType()
|
||||
{
|
||||
$typehint = $this->typehint;
|
||||
|
||||
if (str_ends_with($typehint, '[]')) {
|
||||
return 'array';
|
||||
}
|
||||
|
@ -72,9 +75,38 @@ class Type
|
|||
*/
|
||||
public function getJSONRPCType()
|
||||
{
|
||||
return $this->toPrimitiveType($this->typehint);
|
||||
return $this->getBaseType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base type as one of the supported OpenAPI types
|
||||
*
|
||||
* Formats (eg. int32 or double) are not supported
|
||||
*
|
||||
* @link https://swagger.io/docs/specification/data-models/data-types/
|
||||
* @return string
|
||||
*/
|
||||
public function getOpenApiType()
|
||||
{
|
||||
switch ($this->getBaseType()) {
|
||||
case 'int':
|
||||
return 'integer';
|
||||
case 'bool':
|
||||
return 'boolean';
|
||||
case 'array':
|
||||
return 'array';
|
||||
case 'string':
|
||||
case 'mixed':
|
||||
return 'string';
|
||||
case 'double':
|
||||
case 'float':
|
||||
return 'number';
|
||||
default:
|
||||
return 'object';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If this is an array, return the type of the array elements
|
||||
*
|
||||
|
@ -104,7 +136,7 @@ class Type
|
|||
return $type;
|
||||
}
|
||||
|
||||
$type = $this->toPrimitiveType($this->typehint);
|
||||
$type = $this->getBaseType($this->typehint);
|
||||
|
||||
// primitive types
|
||||
if (in_array($type, ['int', 'string', 'double', 'bool', 'array'])) {
|
||||
|
|
Loading…
Reference in New Issue