Completed
Pull Request — master (#27)
by
unknown
01:55
created

Schema::getHost()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * This file is part of Rebilly.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @see http://rebilly.com
9
 */
10
11
namespace Rebilly\OpenAPI;
12
13
/**
14
 * Schema representation.
15
 */
16
final class Schema
17
{
18
    /**
19
     * Schema definition.
20
     *
21
     * @var object
22
     */
23
    private $schema;
24
25
    /**
26
     * @param object $schema
27
     */
28 4
    public function __construct($schema)
29
    {
30 4
        if (!(isset($schema->openapi) && $schema->openapi === '3.0.0')) {
31 4
            throw new UnexpectedValueException('Unsupported OpenAPI Specification schema');
32
        }
33
34
        $this->schema = $schema;
35
    }
36
37
    /**
38
     * @return string
39
     */
40
    public function getHost()
41
    {
42
        return $this->fetch($this->schema, 'host');
43
    }
44
45
    /**
46
     * @return string
47
     */
48
    public function getBasePath()
49
    {
50
        return $this->fetch($this->schema, 'basePath');
51
    }
52
53
    /**
54
     * @param string $name
55
     *
56
     * @return object
57
     */
58
    public function getDefinition($name)
59
    {
60
        return $this->fetch($this->schema, 'definitions', $name);
61
    }
62
63
    /**
64
     * @return string[]
65
     */
66
    public function getDefinitionNames()
67
    {
68
        return array_keys((array) $this->fetch($this->schema, 'definitions'));
69
    }
70
71
    /**
72
     * @param string $template
73
     *
74
     * @return object
75
     */
76
    public function getPathSchema($template)
77
    {
78
        return $this->fetch($this->schema, 'paths', $template);
79
    }
80
81
    /**
82
     * @return string[]
83
     */
84
    public function getAvailablePaths()
85
    {
86
        return array_keys((array) $this->fetch($this->schema, 'paths'));
87
    }
88
89
    /**
90
     * @param string $template Schema path template.
91
     *
92
     * @return string[]
93
     */
94
    public function getAllowedMethods($template)
95
    {
96
        $schema = $this->getPathSchema($template);
97
        $methods = [
98
            'OPTIONS' => true,
99
            'HEAD' => isset($schema->get),
100
            'GET' => isset($schema->get),
101
            'POST' => isset($schema->post),
102
            'PUT' => isset($schema->put),
103
            'DELETE' => isset($schema->delete),
104
            'PATCH' => isset($schema->patch),
105
        ];
106
107
        return array_keys(array_filter($methods));
108
    }
109
110
    /**
111
     * The transfer protocol for the operation.
112
     * The value overrides the top-level schemes definition.
113
     *
114
     * @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#operationObject
115
     *
116
     * @param string $template
117
     * @param string $method
118
     *
119
     * @return string[]
120
     */
121 View Code Duplication
    public function getSupportedSchemes($template, $method)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
122
    {
123
        $schemes = $this->fetch(
124
            $this->schema,
125
            'paths',
126
            $template,
127
            $method,
128
            'schemes'
129
        );
130
131
        if (!$schemes) {
132
            $schemes = $this->fetch($this->schema, 'schemes');
133
        }
134
135
        return (array) $schemes;
136
    }
137
138
    /**
139
     * @param string $template
140
     * @param string $method
141
     *
142
     * @return object[]
143
     */
144
    public function getRequestHeaderSchemas($template, $method)
145
    {
146
        return $this->getRequestParameters($template, $method, 'header');
147
    }
148
149
    /**
150
     * @param string $template
151
     * @param string $method
152
     *
153
     * @return object|null
154
     */
155
    public function getRequestBodySchema($template, $method)
156
    {
157
        $parameters = $this->getRequestParameters($template, $method, 'body');
158
        $count = count($parameters);
159
160
        if ($count === 0) {
161
            return null;
162
        }
163
164
        if ($count > 1) {
165
            throw new UnexpectedValueException('Multiple body parameters found');
166
        }
167
168
        $body = reset($parameters);
169
170
        if (!isset($body->schema)) {
171
            throw new UnexpectedValueException('Invalid body parameter definition');
172
        }
173
174
        return $body->schema;
175
    }
176
177
    /**
178
     * @param string $template
179
     * @param string $method
180
     *
181
     * @return object[]
182
     */
183
    public function getRequestPathParameters($template, $method)
184
    {
185
        return $this->getRequestParameters($template, $method, 'path');
186
    }
187
188
    /**
189
     * @param string $template
190
     * @param string $method
191
     *
192
     * @return object[]
193
     */
194
    public function getRequestQueryParameters($template, $method)
195
    {
196
        return $this->getRequestParameters($template, $method, 'query');
197
    }
198
199
    /**
200
     * @param string $template
201
     * @param string $method
202
     *
203
     * @return string[]
204
     */
205 View Code Duplication
    public function getRequestContentTypes($template, $method)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
    {
207
        $items = $this->fetch($this->schema, 'paths', $template, $method, 'consumes');
208
209
        if (!$items) {
210
            $items = $this->fetch($this->schema, 'consumes');
211
        }
212
213
        return (array) $items;
214
    }
215
216
    /**
217
     * @param string $template
218
     * @param string $method
219
     *
220
     * @return int[]
221
     */
222
    public function getResponseCodes($template, $method)
223
    {
224
        return array_map(
225
            'intval',
226
            array_filter(
227
                array_keys((array) $this->fetch($this->schema, 'paths', $template, $method, 'responses')),
228
                'is_numeric'
229
            )
230
        );
231
    }
232
233
    /**
234
     * @param string $template
235
     * @param string $method
236
     *
237
     * @return string[]
238
     */
239 View Code Duplication
    public function getResponseContentTypes($template, $method)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
240
    {
241
        $items = $this->fetch($this->schema, 'paths', $template, $method, 'produces');
242
243
        if (!$items) {
244
            $items = $this->fetch($this->schema, 'produces');
245
        }
246
247
        return (array) $items;
248
    }
249
250
    /**
251
     * @param string $template
252
     * @param string $method
253
     * @param string $status
254
     *
255
     * TODO: Normalize headers list to JSON schema (seems it is validator deals)
256
     * TODO: If status does not defined, check default response declaration
257
     *
258
     * @return object[]
259
     */
260
    public function getResponseHeaderSchemas($template, $method, $status)
261
    {
262
        return (array) $this->fetch(
263
            $this->schema,
264
            'paths',
265
            $template,
266
            $method,
267
            'responses',
268
            $status,
269
            'headers'
270
        );
271
    }
272
273
    /**
274
     * Returns body schema.
275
     *
276
     * @param string $template
277
     * @param string $method
278
     * @param string $status
279
     *
280
     * @return object|null
281
     */
282
    public function getResponseBodySchema($template, $method, $status)
283
    {
284
        return $this->fetch(
285
            $this->schema,
286
            'paths',
287
            $template,
288
            $method,
289
            'responses',
290
            $status,
291
            'schema'
292
        );
293
    }
294
295
    /**
296
     * @param $schema
297
     * @param array ...$paths
298
     *
299
     * @return mixed
300
     */
301
    private static function fetch($schema, ...$paths)
302
    {
303
        foreach ($paths as $path) {
304
            if (!isset($schema->{$path})) {
305
                return null;
306
            }
307
308
            $schema = $schema->{$path};
309
        }
310
311
        return $schema;
312
    }
313
314
    /**
315
     * A list of parameters that are applicable for this operation.
316
     *
317
     * If a parameter is already defined at the Path Item,
318
     * the new definition will override it, but can never remove it.
319
     *
320
     * @param string $template
321
     * @param string $method
322
     * @param string $location
323
     *
324
     * @return object[]
325
     */
326
    private function getRequestParameters($template, $method, $location)
327
    {
328
        $path = $this->fetch($this->schema, 'paths', $template);
329
330
        $operationParameters = $this->normalizeRequestParameters(
331
            (array) $this->fetch($path, $method, 'parameters'),
332
            $location
333
        );
334
335
        $pathParameters = $this->normalizeRequestParameters(
336
            (array) $this->fetch($path, 'parameters'),
337
            $location
338
        );
339
340
        return $operationParameters + $pathParameters;
341
    }
342
343
    /**
344
     * Normalizes parameters definitions.
345
     *
346
     * Filter parameters by location, and use name as list index.
347
     *
348
     * @param array $parameters
349
     * @param string $location
350
     *
351
     * @return object[]
352
     */
353
    private function normalizeRequestParameters(array $parameters, $location)
354
    {
355
        $schemas = [];
356
357
        foreach ($parameters as $parameter) {
358
            if ($parameter->in !== $location) {
359
                continue;
360
            }
361
362
            if (isset($schemas[$parameter->name])) {
363
                throw new UnexpectedValueException('Multiple parameters found');
364
            }
365
366
            $schemas[$parameter->name] = clone $parameter;
367
            unset($schemas[$parameter->name]->name, $schemas[$parameter->name]->in);
368
        }
369
370
        return $schemas;
371
    }
372
}
373