|
1
|
|
|
<?php |
|
2
|
|
|
/* |
|
3
|
|
|
* This file is part of the KleijnWeb\SwaggerBundle package. |
|
4
|
|
|
* |
|
5
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
6
|
|
|
* file that was distributed with this source code. |
|
7
|
|
|
*/ |
|
8
|
|
|
|
|
9
|
|
|
namespace KleijnWeb\SwaggerBundle\Document; |
|
10
|
|
|
|
|
11
|
|
|
use JsonSchema\RefResolver; |
|
12
|
|
|
use JsonSchema\Uri\UriRetriever; |
|
13
|
|
|
use Symfony\Component\Yaml\Yaml; |
|
14
|
|
|
|
|
15
|
|
|
/** |
|
16
|
|
|
* @author John Kleijn <[email protected]> |
|
17
|
|
|
*/ |
|
18
|
|
|
class SwaggerDocument |
|
19
|
|
|
{ |
|
20
|
|
|
/** |
|
21
|
|
|
* @var string |
|
22
|
|
|
*/ |
|
23
|
|
|
private $pathFileName; |
|
24
|
|
|
|
|
25
|
|
|
/** |
|
26
|
|
|
* @var \ArrayObject |
|
27
|
|
|
*/ |
|
28
|
|
|
private $definition; |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* @param $pathFileName |
|
32
|
|
|
*/ |
|
33
|
|
|
public function __construct($pathFileName) |
|
34
|
|
|
{ |
|
35
|
|
|
if (!is_file($pathFileName)) { |
|
36
|
|
|
throw new \InvalidArgumentException( |
|
37
|
|
|
"Document file '$pathFileName' does not exist'" |
|
38
|
|
|
); |
|
39
|
|
|
} |
|
40
|
|
|
|
|
41
|
|
|
$data = Yaml::parse(file_get_contents($pathFileName)); |
|
42
|
|
|
$data = self::resolveSelfReferences($data, $data); |
|
43
|
|
|
|
|
44
|
|
|
$this->pathFileName = $pathFileName; |
|
45
|
|
|
$this->definition = new \ArrayObject($data, \ArrayObject::ARRAY_AS_PROPS | \ArrayObject::STD_PROP_LIST); |
|
46
|
|
|
} |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* @return array |
|
50
|
|
|
*/ |
|
51
|
|
|
public function getDefinition() |
|
52
|
|
|
{ |
|
53
|
|
|
return $this->definition; |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* @return array |
|
58
|
|
|
*/ |
|
59
|
|
|
public function getPathDefinitions() |
|
60
|
|
|
{ |
|
61
|
|
|
return $this->definition->paths; |
|
|
|
|
|
|
62
|
|
|
} |
|
63
|
|
|
|
|
64
|
|
|
/** |
|
65
|
|
|
* @return array |
|
66
|
|
|
*/ |
|
67
|
|
|
public function getResourceSchemas() |
|
68
|
|
|
{ |
|
69
|
|
|
return $this->definition->definitions; |
|
|
|
|
|
|
70
|
|
|
} |
|
71
|
|
|
|
|
72
|
|
|
/** |
|
73
|
|
|
* @return string |
|
74
|
|
|
*/ |
|
75
|
|
|
public function getBasePath() |
|
76
|
|
|
{ |
|
77
|
|
|
return $this->definition->basePath; |
|
|
|
|
|
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
|
/** |
|
81
|
|
|
* @param string $path |
|
82
|
|
|
* @param string $method |
|
83
|
|
|
* |
|
84
|
|
|
* @return array |
|
85
|
|
|
*/ |
|
86
|
|
|
public function getOperationDefinition($path, $method) |
|
87
|
|
|
{ |
|
88
|
|
|
$paths = $this->getPathDefinitions(); |
|
89
|
|
|
if (!isset($paths[$path])) { |
|
90
|
|
|
throw new \InvalidArgumentException("Path '$path' not in Swagger document"); |
|
91
|
|
|
} |
|
92
|
|
|
$method = strtolower($method); |
|
93
|
|
|
if (!isset($paths[$path][$method])) { |
|
94
|
|
|
throw new \InvalidArgumentException("Method '$method' not supported for path '$path'"); |
|
95
|
|
|
} |
|
96
|
|
|
|
|
97
|
|
|
return $paths[$path][$method]; |
|
98
|
|
|
} |
|
99
|
|
|
|
|
100
|
|
|
/** |
|
101
|
|
|
* @return array |
|
102
|
|
|
*/ |
|
103
|
|
|
public function getArrayCopy() |
|
104
|
|
|
{ |
|
105
|
|
|
return $this->definition->getArrayCopy(); |
|
106
|
|
|
} |
|
107
|
|
|
|
|
108
|
|
|
/** |
|
109
|
|
|
* @param null $targetPath |
|
110
|
|
|
* |
|
111
|
|
|
* @return void |
|
112
|
|
|
*/ |
|
113
|
|
|
public function write($targetPath = null) |
|
114
|
|
|
{ |
|
115
|
|
|
$data = $this->getArrayCopy(); |
|
116
|
|
|
$data = self::unresolveSelfReferences($data, $data); |
|
117
|
|
|
$yaml = Yaml::dump($data, 10, 2); |
|
118
|
|
|
$yaml = str_replace(': { }', ': []', $yaml); |
|
119
|
|
|
file_put_contents($targetPath ?: $this->pathFileName, $yaml); |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* Cloning will break things |
|
124
|
|
|
*/ |
|
125
|
|
|
private function __clone() |
|
126
|
|
|
{ |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
|
|
/** |
|
130
|
|
|
* @param array $segments |
|
131
|
|
|
* @param array $context |
|
132
|
|
|
* |
|
133
|
|
|
* @return mixed |
|
134
|
|
|
*/ |
|
135
|
|
|
private static function lookupUsingSegments(array $segments, array $context) |
|
136
|
|
|
{ |
|
137
|
|
|
$segment = array_shift($segments); |
|
138
|
|
|
if (isset($context[$segment])) { |
|
139
|
|
|
if (!count($segments)) { |
|
140
|
|
|
return $context[$segment]; |
|
141
|
|
|
} |
|
142
|
|
|
|
|
143
|
|
|
return self::lookupUsingSegments($segments, $context[$segment]); |
|
144
|
|
|
} |
|
145
|
|
|
|
|
146
|
|
|
return null; |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
/** |
|
150
|
|
|
* @param array $doc |
|
151
|
|
|
* @param array $data |
|
152
|
|
|
* |
|
153
|
|
|
* @return array |
|
154
|
|
|
*/ |
|
155
|
|
|
private function resolveSelfReferences(array $doc, array &$data) |
|
156
|
|
|
{ |
|
157
|
|
|
foreach ($data as $key => &$value) { |
|
158
|
|
|
if (is_array($value)) { |
|
159
|
|
|
$value = self::resolveSelfReferences($doc, $value); |
|
160
|
|
|
} |
|
161
|
|
|
if ($key === '$ref' && '#' === $value[0]) { |
|
162
|
|
|
$data = self::lookupUsingSegments( |
|
163
|
|
|
explode('/', trim(substr($value, 1), '/')), |
|
164
|
|
|
$doc |
|
165
|
|
|
); |
|
166
|
|
|
$data['id'] = $value; |
|
167
|
|
|
// Use something a little less generic for more reliable qnd restoring of original |
|
168
|
|
|
$data['x-swagger-id'] = $value; |
|
169
|
|
|
} |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
return $data; |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
/** |
|
176
|
|
|
* @param array $doc |
|
177
|
|
|
* @param array $data |
|
178
|
|
|
* |
|
179
|
|
|
* @return array |
|
180
|
|
|
*/ |
|
181
|
|
|
private function unresolveSelfReferences(array $doc, array &$data) |
|
182
|
|
|
{ |
|
183
|
|
|
foreach ($data as $key => &$value) { |
|
184
|
|
|
if (is_array($value)) { |
|
185
|
|
|
$value = self::unresolveSelfReferences($doc, $value); |
|
186
|
|
|
} |
|
187
|
|
|
if ($key === 'x-swagger-id') { |
|
188
|
|
|
$data = ['$ref' => $value]; |
|
189
|
|
|
} |
|
190
|
|
|
} |
|
191
|
|
|
|
|
192
|
|
|
return $data; |
|
193
|
|
|
} |
|
194
|
|
|
} |
|
195
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.