-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSchema.php
More file actions
167 lines (140 loc) · 4.57 KB
/
Copy pathSchema.php
File metadata and controls
167 lines (140 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<?php
declare(strict_types=1);
namespace OasFake;
use cebe\openapi\Reader;
use cebe\openapi\spec\OpenApi;
use cebe\openapi\spec\Operation;
use cebe\openapi\spec\PathItem;
use cebe\openapi\spec\Server as CebeServer;
use function is_string;
use OasFake\Exception\SchemaNotFoundException;
/**
* Wrapper around an OpenAPI specification with factory methods for loading.
*/
final class Schema
{
private function __construct(private OpenApi $openApi)
{
}
/**
* Load an OpenAPI schema from a file path.
*
* Automatically detects JSON or YAML format from the file extension.
*
* @param string $path Path to the OpenAPI schema file
*
* @throws SchemaNotFoundException If the file does not exist
*/
public static function fromFile(string $path): self
{
if (!file_exists($path)) {
throw SchemaNotFoundException::forPath($path);
}
$resolvedPath = realpath($path);
if ($resolvedPath === false) {
throw SchemaNotFoundException::forPath($path);
}
$ext = strtolower(pathinfo($resolvedPath, PATHINFO_EXTENSION));
$openApi = $ext === 'json'
? Reader::readFromJsonFile($resolvedPath, OpenApi::class, true)
: Reader::readFromYamlFile($resolvedPath, OpenApi::class, true);
return new self($openApi);
}
/**
* Parse an OpenAPI schema from a string.
*
* @param string $content The raw schema content
* @param string $format The format of the content ('yaml' or 'json')
*/
public static function fromString(string $content, string $format = 'yaml'): self
{
$openApi = $format === 'json'
? Reader::readFromJson($content, OpenApi::class)
: Reader::readFromYaml($content, OpenApi::class);
return new self($openApi);
}
/**
* Create a Schema instance from an existing OpenApi object.
*
* @param OpenApi $openApi The parsed OpenAPI specification
*/
public static function fromOpenApi(OpenApi $openApi): self
{
return new self($openApi);
}
/**
* Return the underlying OpenApi specification object.
*/
public function openApi(): OpenApi
{
return $this->openApi;
}
/**
* Return the effective server URLs used by operations, with variables substituted.
*
* @return list<string>
*/
public function serverUrls(): array
{
$urls = [];
if ($this->openApi->paths !== null) {
/** @var PathItem $pathItem */
foreach ($this->openApi->paths as $path => $pathItem) {
if (!is_string($path)) {
continue;
}
foreach ($pathItem->getOperations() as $operation) {
foreach ($this->effectiveServerUrls($pathItem, $operation) as $url) {
$urls[$url] = true;
}
}
}
}
if ($urls === []) {
return $this->effectiveServerUrls();
}
return array_keys($urls);
}
/**
* Return the server URLs that apply to one operation.
*
* Operation-level servers override path-level servers, which override root-level servers.
*
* @return list<string>
*/
public function effectiveServerUrls(?PathItem $pathItem = null, ?Operation $operation = null): array
{
if ($operation !== null && $operation->servers !== null && $operation->servers !== []) {
return $this->resolveServerUrls($operation->servers);
}
if ($pathItem !== null && $pathItem->servers !== null && $pathItem->servers !== []) {
return $this->resolveServerUrls($pathItem->servers);
}
if ($this->openApi->servers !== null && $this->openApi->servers !== []) {
return $this->resolveServerUrls($this->openApi->servers);
}
return ['/'];
}
/**
* @param array<int|string, CebeServer> $servers
*
* @return list<string>
*/
private function resolveServerUrls(array $servers): array
{
$urls = [];
foreach ($servers as $server) {
if (!$server instanceof CebeServer) {
continue;
}
$url = $server->url;
if ($server->variables !== null) {
foreach ($server->variables as $name => $variable) {
$url = str_replace('{' . $name . '}', $variable->default, $url);
}
}
$urls[] = $url;
}
return $urls === [] ? ['/'] : $urls;
}
}