1<?php 2 3namespace dokuwiki\Remote\OpenApiDoc; 4 5class Type implements \Stringable 6{ 7 protected $typehint; 8 protected $context; 9 10 /** 11 * @param string $typehint The typehint as read from the docblock 12 * @param string $context A fully qualified class name in which context the typehint is used 13 */ 14 public function __construct($typehint, $context = '') 15 { 16 $this->typehint = $typehint; 17 $this->context = $context; 18 } 19 20 /** 21 * Return the typehint as read from the docblock 22 * 23 * @return string 24 */ 25 public function __toString(): string 26 { 27 return (string) $this->typehint; 28 } 29 30 /** 31 * Return the base type 32 * 33 * This is the type this variable is. Eg. a string[] is an array. 34 * 35 * @return string 36 */ 37 public function getBaseType() 38 { 39 $typehint = $this->typehint; 40 41 if (str_ends_with($typehint, '[]')) { 42 return 'array'; 43 } 44 45 if (in_array($typehint, ['boolean', 'false', 'true'])) { 46 return 'bool'; 47 } 48 49 if (in_array($typehint, ['integer', 'date'])) { 50 return 'int'; 51 } 52 53 if ($typehint === 'file') { 54 return 'string'; 55 } 56 57 // fully qualified class name 58 if ($typehint[0] === '\\') { 59 return ltrim($typehint, '\\'); 60 } 61 62 // relative class name, try to resolve 63 if ($this->context && ctype_upper($typehint[0])) { 64 return ClassResolver::getInstance()->resolve($typehint, $this->context); 65 } 66 67 return $typehint; 68 } 69 70 /** 71 * Return a primitive type understood by the XMLRPC server 72 * 73 * @param string $typehint 74 * @return string 75 */ 76 public function getJSONRPCType() 77 { 78 return $this->getBaseType(); 79 } 80 81 /** 82 * Get the base type as one of the supported OpenAPI types 83 * 84 * Formats (eg. int32 or double) are not supported 85 * 86 * @link https://swagger.io/docs/specification/data-models/data-types/ 87 * @return string 88 */ 89 public function getOpenApiType() 90 { 91 return match ($this->getBaseType()) { 92 'int' => 'integer', 93 'bool' => 'boolean', 94 'array' => 'array', 95 'string', 'mixed' => 'string', 96 'double', 'float' => 'number', 97 default => 'object', 98 }; 99 } 100 101 102 /** 103 * If this is an array, return the type of the array elements 104 * 105 * @return Type|null null if this is not a typed array 106 */ 107 public function getSubType() 108 { 109 $type = $this->typehint; 110 if (!str_ends_with($type, '[]')) { 111 return null; 112 } 113 $type = substr($type, 0, -2); 114 return new Type($type, $this->context); 115 } 116 117 /** 118 * Return a type understood by the XMLRPC server 119 * 120 * @return string 121 */ 122 public function getXMLRPCType() 123 { 124 $type = $this->typehint; 125 126 // keep custom types 127 if (in_array($type, ['date', 'file', 'struct'])) { 128 return $type; 129 } 130 131 $type = $this->getBaseType($this->typehint); 132 133 // primitive types 134 if (in_array($type, ['int', 'string', 'double', 'bool', 'array'])) { 135 return $type; 136 } 137 138 // everything else is an object 139 return 'object'; //should this return 'struct'? 140 } 141} 142