Last active
February 29, 2024 07:18
-
-
Save d8ahazard/087e2e31f192de408378840f8b56b49e to your computer and use it in GitHub Desktop.
Auto-generate PHP class from swagger documentation...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// You need to have guzzleHttp installed, and require the vendor path here... | |
header('content-type:text/plain'); | |
$url = $_GET['url']; | |
$swaggerApi = json_decode(file_get_contents("$url"), true); | |
$outFile = pathinfo($url)['filename'] . ".php"; | |
$paths = $swaggerApi['paths']; | |
$defs = $swaggerApi['definitions']; | |
$pathParts = []; | |
$i = 0; | |
$docLines2 = []; | |
$methodStrings = ""; | |
$docLines = []; | |
$className = $swaggerApi['info']['title']; | |
$className = trim(str_replace("Api", "", $className)); | |
$docHeader = '<?php | |
use GuzzleHttp\Client; | |
class '.$className.' { | |
protected $url; | |
protected $apiKey; | |
public function __construct($url, $apiKey) { | |
$this->url = rtrim($url, "/"); // Example: http://127.0.0.1:8989 (no trailing forward-backward slashes) | |
$this->apiKey = $apiKey; | |
} | |
'; | |
$types = [ | |
'boolean'=>'bool', | |
'integer'=>'int', | |
'string'=>'string', | |
'array'=>'array' | |
]; | |
$methods = []; | |
$pathParts = []; | |
foreach($paths as $key => $path) { | |
$path_parts = explode("/", $key); | |
foreach($path_parts as $part) { | |
$pathParts[$part] = ($pathParts[$part] ?? 1) + 1; | |
} | |
} | |
$masterPath = []; | |
foreach($pathParts as $pathPart=>$partCount) { | |
if ($partCount == (count($paths) + 1) && trim($pathPart)) { | |
write_log("Section $pathPart matches count"); | |
array_push($masterPath, $pathPart); | |
} | |
} | |
$masterPath = "/". join("/", $masterPath); | |
foreach($paths as $key => $path) { | |
$docLine = []; | |
$key = str_replace($masterPath, "", $key); | |
$path_parts = explode("/", $key); | |
$get = $path['get'] ?? false; | |
$post = $path['post'] ?? false; | |
$put = $path['put'] ?? false; | |
$delete = $path['delete'] ?? false; | |
if ($get) $method = "get"; | |
if ($post) $method = "post"; | |
if ($put) $method = "put"; | |
if ($delete) $method = "delete"; | |
$summary = $path[$method]['summary'] ?? ""; | |
$name = $method; | |
$p = 0; | |
if (empty($pathParts)) $pathParts = $path_parts; | |
foreach ($path_parts as &$part) { | |
if (!preg_match("/{/", $part)) { | |
$name .= ucfirst($part); | |
} else { | |
$part = str_replace('{', '$', $part); | |
$part = str_replace('}', "", $part); | |
} | |
$p++; | |
} | |
//$name = titleCase($name); | |
$uri = join('/', $path_parts); | |
$uri = ltrim($uri,"/"); | |
$params = $path[$method]['parameters'] ?? []; | |
$strDesc = ""; | |
$new = []; | |
$optional = []; | |
foreach($params as $param) { | |
if ($param['type'] !== 'apiKey') { | |
if ($param['required']) { | |
array_push($new, $param); | |
} else { | |
array_push($optional, $param); | |
} | |
} | |
} | |
$params = $new; | |
foreach($optional as $add) array_push($params, $add); | |
$docLine[] = '/**'; | |
$docLine[] = "* $name"; | |
$docLine[] = "* $summary"; | |
$docLine[] = "*"; | |
$paramStrings = []; | |
$paramNames = []; | |
$j = 0; | |
$body = false; | |
$queryString = []; | |
foreach ($params as $param) { | |
$defProps = []; | |
$paramData = []; | |
$ref = $param['schema']['$ref'] ?? false; | |
if ($ref) { | |
$ref = str_replace('#/definitions/', "", $ref); | |
$defProps = $defs[$ref]['properties'] ?? []; | |
$paramData = sortDefProps($defProps); | |
if ($params['in'] ?? "" == "body") { | |
$body = $paramData; | |
} | |
} | |
$paramName = $param['name']; | |
$in = $param["in"] ?? false; | |
if ($in == "query") $queryString[$paramName] = "$" . $paramName; | |
$required = $param['required'] ? "(required)" : "(optional)"; | |
$description = $required . " " . $param['description']; | |
$type = $types[$param['type']] ?? $param['type'] ?? "array"; | |
if (! $param['required']) { | |
$typeLine = "bool | $type"; | |
} else { | |
$typeLine = $type; | |
} | |
$enum = $param['enum'] ?? false; | |
if (is_array($enum)) $description .= " '".join(" | ", $enum) ."'"; | |
$docLine[] = '* @param '.$typeLine.' $'.$paramName. ' - '. $description; | |
if (count($paramData)) { | |
$jsonLines = explode("\n", json_encode($paramData,JSON_PRETTY_PRINT)); | |
foreach($jsonLines as $line) { | |
$docLine[] = "* $line"; | |
} | |
} | |
$reqString = $param['required'] ? "" : "=false"; | |
$paramStrings[] = '$' . $paramName . $reqString; | |
$paramNames[] = '$' . $paramName; | |
$j++; | |
} | |
if (count($queryString)) { | |
$uri .= "?".join("&",$queryString); | |
} | |
$retType = $path[$method]['produces'][0] ?? false; | |
$retType = $retType ? "($retType)" : ""; | |
$docLine[] = "*"; | |
$docLine[] = "* @return string $retType"; | |
$responseRef = $path[$method]['responses']['200']['schema']['$ref'] ?? false; | |
if ($responseRef) { | |
$responseRef = str_replace('#/definitions/', "", $responseRef); | |
$defProps = $defs[$responseRef]['properties'] ?? []; | |
$paramData = sortDefProps($defProps); | |
if (count($paramData)) { | |
$jsonLines = explode("\n", json_encode($paramData,JSON_PRETTY_PRINT)); | |
foreach($jsonLines as $line) { | |
$docLine[] = "* $line"; | |
} | |
} | |
} | |
$docLine[] = '*/'; | |
$paramVal = isset($paramNames[0]) ? $paramNames[0] : 'false'; | |
$ps = count($paramStrings) ? join(", ", $paramStrings) : ""; | |
$docLine[] = "function ${name}(${ps}) {"; | |
$docLine[] = "\t".'$uri = "'.$uri.'";'; | |
if ($method == 'get') { | |
$docLine[] = "\t".'return $this->processRequest($uri);'; | |
} else { | |
$docLine[] = "\t".'$method = "'.$method.'";'; | |
$docLine[] = "\t".'return $this->processRequest($uri, '. $paramVal .', $method);'; | |
} | |
$docLine[] = '}'; | |
$docLine[] = ""; | |
$i++; | |
foreach($docLine as $dl) array_push($docLines2, $dl); | |
if (in_array($name, $methods)) { | |
echo("WARNING: Duplicate method name '$name' detected.".PHP_EOL.PHP_EOL); | |
} else { | |
array_push($methods, $name); | |
} | |
} | |
echo $docHeader; | |
echo PHP_EOL; | |
foreach($docLines2 as $line) { | |
echo "\t$line".PHP_EOL; | |
} | |
#TODO: Make this figure out a base URL shared across all endpoints, use that here. | |
echo '/** | |
* Process requests with Guzzle | |
* | |
* @param string $uri | |
* @param string $type - Default is "get", also accepts post/put/delete | |
* @param bool | array $body - A JSON array of key/values to submit on POST/PUT | |
* @return bool|\Psr\Http\Message\ResponseInterface | |
*/ | |
protected function _request(string $uri, $body, $type) { | |
$client = new Client(); | |
$url = $this->url . "'.$masterPath.'/$uri"; | |
write_log("URL is $url"); | |
$options = []; | |
$options[\'headers\'] = [\'apiKey\' => $this->apiKey]; | |
if ($body) $options[\'json\'] = $body; | |
write_log("Options for $type: ".json_encode($options)); | |
switch ($type) { | |
case "get": | |
return $client->get($url, $options); | |
break; | |
case "post": | |
return $client->post($url, $options); | |
break; | |
case "put": | |
return $client->put($url, $options); | |
break; | |
case "delete": | |
return $client->delete($url, $options); | |
break; | |
} | |
return false; | |
} | |
/** | |
* Process requests, catch exceptions, return json response | |
* | |
* @param string $uri | |
* @param bool | array $body - A JSON array of key/values to submit on POST/PUT | |
* @param string $type | |
* @return string - A JSON response | |
*/ | |
protected function processRequest($uri, $body = false, $type = "get") { | |
try { | |
$response = $this->_request($uri, $body, $type); | |
} catch (\Exception $e) { | |
return json_encode([\'error\' => array( | |
\'msg\' => $e->getMessage(), | |
\'code\' => $e->getCode()) | |
]); | |
} | |
return $response->getBody()->getContents(); | |
} | |
} | |
'; | |
write_log("Final master path: ".json_encode($pathParts)); | |
die(); | |
function sortDefProps($defProps) { | |
$types = [ | |
'boolean'=>'bool', | |
'integer'=>'int', | |
'string'=>'string', | |
'array'=>'array' | |
]; | |
$paramData = []; | |
foreach($defProps as $propName => $data) { | |
$type = $data['type']; | |
if ($type !== 'array') { | |
$paramData[$propName] = $types[$type] ?? $type; | |
} else { | |
$ref2 = str_replace('#/definitions/', "", $data['items']['$ref']); | |
$defProps2 = $defs[$ref2]['properties'] ?? []; | |
$paramData[$propName] = "array - " . json_encode(sortDefProps($defProps2),true); | |
} | |
} | |
return $paramData; | |
} | |
function titleCase($title, $words) { | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment