From f80a6526ed1c78145e31efe8d04979861c55cc39 Mon Sep 17 00:00:00 2001 From: Eddie Kohler Date: Fri, 13 Sep 2024 12:14:07 -0400 Subject: [PATCH] API spec internals --- batch/apispec.php | 71 +++++++++++++++++++++++++---------------------- lib/base.php | 2 +- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/batch/apispec.php b/batch/apispec.php index f39eed8b72..f207741374 100644 --- a/batch/apispec.php +++ b/batch/apispec.php @@ -14,21 +14,31 @@ class APISpec_Batch { public $user; /** @var array> */ public $api_map; - /** @var array */ - public $paths = []; - /** @var array */ - public $schemas = []; - /** @var array */ - public $parameters = []; + /** @var object */ + private $j; + /** @var object */ + private $paths; + /** @var ?object */ + private $schemas; + /** @var ?object */ + private $parameters; function __construct(Conf $conf, $arg) { $this->conf = $conf; $this->user = $conf->root_user(); $this->api_map = $conf->api_map(); + $this->j = (object) []; } /** @return int */ function run() { + $mj = $this->j; + $mj->openapi = "3.1.0"; + $info = $mj->info = $mj->info ?? (object) []; + $info->title = $info->title ?? "HotCRP"; + $info->version = $info->version ?? "0.1"; + + $this->paths = $mj->paths = $mj->paths ?? (object) []; $fns = array_keys($this->api_map); sort($fns); foreach ($fns as $fn) { @@ -41,22 +51,8 @@ function run() { $this->expand_paths($fn); } } - $j = [ - "openapi" => "3.1.0", - "info" => [ - "title" => "HotCRP", - "version" => "0.1" - ], - "paths" => $this->paths, - "components" => [] - ]; - if (!empty($this->schemas)) { - $j["components"]["schemas"] = $this->schemas; - } - if (!empty($this->parameters)) { - $j["components"]["parameters"] = $this->parameters; - } - fwrite(STDOUT, json_encode($j, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . "\n"); + + fwrite(STDOUT, json_encode($this->j, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n"); return 0; } @@ -125,30 +121,35 @@ private function expand_paths($fn) { * @param array $known * @param object $j */ private function expand_path_method($path, $method, $known, $j) { - $this->paths[$path] = $this->paths[$path] ?? []; - $this->paths[$path][strtolower($method)] = $x = (object) []; - $this->expand_request($x, $known, $j); - $this->expand_response($x, $j); + $pathj = $this->paths->$path = $this->paths->$path ?? (object) []; + $lmethod = strtolower($method); + $xj = $pathj->$lmethod = $pathj->$lmethod ?? (object) []; + $this->expand_request($xj, $known, $j); + $this->expand_response($xj, $j); } /** @param string $name * @return object */ private function resolve_common_schema($name) { - if (!isset($this->schemas[$name])) { + if ($this->schemas === null) { + $compj = $this->j->components = $this->j->components ?? (object) []; + $this->schemas = $compj->schemas = $compj->schemas ?? (object) []; + } + if (!isset($this->schemas->$name)) { if ($name === "pid") { - $this->schemas[$name] = (object) [ + $this->schemas->$name = (object) [ "type" => "integer", "minimum" => 1 ]; } else if ($name === "ok") { return (object) ["type" => "boolean"]; } else if ($name === "message_list") { - $this->schemas[$name] = (object) [ + $this->schemas->$name = (object) [ "type" => "list", "items" => $this->resolve_common_schema("message") ]; } else if ($name === "message") { - $this->schemas[$name] = (object) [ + $this->schemas->$name = (object) [ "type" => "object", "required" => ["status"], "properties" => (object) [ @@ -170,16 +171,20 @@ private function resolve_common_schema($name) { /** @param string $name * @return object */ private function resolve_common_param($name) { - if (!isset($this->parameters[$name])) { + if ($this->parameters === null) { + $compj = $this->j->components = $this->j->components ?? (object) []; + $this->parameters = $compj->parameters = $compj->parameters ?? (object) []; + } + if (!isset($this->parameters->$name)) { if ($name === "p") { - $this->parameters["p"] = (object) [ + $this->parameters->p = (object) [ "name" => "p", "in" => "path", "required" => true, "schema" => $this->resolve_common_schema("pid") ]; } else if ($name === "redirect") { - $this->parameters["redirect"] = (object) [ + $this->parameters->redirect = (object) [ "name" => "redirect", "in" => "query", "required" => false, diff --git a/lib/base.php b/lib/base.php index 65277035db..5250b5b676 100644 --- a/lib/base.php +++ b/lib/base.php @@ -498,7 +498,7 @@ function json_encode_browser($x, $flags = 0) { /** @return string */ function json_encode_db($x, $flags = 0) { - return json_encode($x, $flags | JSON_UNESCAPED_UNICODE); + return json_encode($x, $flags | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } /** @param ?string $x