Completed
Pull Request — master (#25)
by
unknown
05:01
created

SwaggerSchema::getResponseParameters()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 3
1
<?php
2
/**
3
 * User: jg
4
 * Date: 22/05/17
5
 * Time: 09:29
6
 */
7
8
namespace ByJG\Swagger;
9
10
use ByJG\Swagger\Exception\DefinitionNotFoundException;
11
use ByJG\Swagger\Exception\HttpMethodNotFoundException;
12
use ByJG\Swagger\Exception\InvalidDefinitionException;
13
use ByJG\Swagger\Exception\NotMatchedException;
14
use ByJG\Swagger\Exception\PathNotFoundException;
15
16
class SwaggerSchema
17
{
18
    protected $jsonFile;
19
    protected $allowNullValues;
20
    protected $specificationVersion;
21
22
    const SWAGGER_PATHS="paths";
23
    const SWAGGER_PARAMETERS="parameters";
24
25
    public function __construct($jsonFile, $allowNullValues = false)
26
    {
27
        $this->jsonFile = json_decode($jsonFile, true);
28
        $this->allowNullValues = (bool) $allowNullValues;
29
        $this->specificationVersion = isset($this->jsonFile['swagger']) ? '2' : '3';
30
    }
31
32
    /**
33
     * Returns the major specification version
34
     * @return string
35
     */
36
    public function getSpecificationVersion()
37
    {
38
        return $this->specificationVersion;
39
    }
40
41
    public function getServerUrl()
42
    {
43
        return isset($this->jsonFile['servers']) ? $this->jsonFile['servers'][0]['url'] : '';
44
    }
45
46
    public function getHttpSchema()
47
    {
48
        return isset($this->jsonFile['schemes']) ? $this->jsonFile['schemes'][0] : '';
49
    }
50
51
    public function getHost()
52
    {
53
        return isset($this->jsonFile['host']) ? $this->jsonFile['host'] : '';
54
    }
55
56
    public function getBasePath()
57
    {
58
        if ($this->getSpecificationVersion() === '3') {
59
            $basePath =isset($this->jsonFile['servers']) ? explode('/', $this->jsonFile['servers'][0]['url']) : '';
60
            return is_array($basePath) ? '/' . end($basePath) : $basePath;
61
        }
62
63
        return isset($this->jsonFile['basePath']) ? $this->jsonFile['basePath'] : '';
64
    }
65
66
    /**
67
     * @param $path
68
     * @param $method
69
     * @return mixed
70
     * @throws \ByJG\Swagger\Exception\HttpMethodNotFoundException
71
     * @throws \ByJG\Swagger\Exception\NotMatchedException
72
     * @throws \ByJG\Swagger\Exception\PathNotFoundException
73
     */
74
    public function getPathDefinition($path, $method)
75
    {
76
        $method = strtolower($method);
77
78
        $path = preg_replace('~^' . $this->getBasePath() . '~', '', $path);
79
80
        // Try direct match
81
        if (isset($this->jsonFile[self::SWAGGER_PATHS][$path])) {
82
            if (isset($this->jsonFile[self::SWAGGER_PATHS][$path][$method])) {
83
                return $this->jsonFile[self::SWAGGER_PATHS][$path][$method];
84
            }
85
            throw new HttpMethodNotFoundException("The http method '$method' not found in '$path'");
86
        }
87
88
        // Try inline parameter
89
        foreach (array_keys($this->jsonFile[self::SWAGGER_PATHS]) as $pathItem) {
90
            if (strpos($pathItem, '{') === false) {
91
                continue;
92
            }
93
94
            $pathItemPattern = '~^' . preg_replace('~\{(.*?)\}~', '(?<\1>[^/]+)', $pathItem) . '$~';
95
96
            $matches = [];
97
            if (preg_match($pathItemPattern, $path, $matches)) {
98
                $pathDef = $this->jsonFile[self::SWAGGER_PATHS][$pathItem];
99
                if (!isset($pathDef[$method])) {
100
                    throw new HttpMethodNotFoundException("The http method '$method' not found in '$path'");
101
                }
102
103
                $this->validateArguments('path', $pathDef[$method][self::SWAGGER_PARAMETERS], $matches);
104
105
                return $pathDef[$method];
106
            }
107
        }
108
109
        throw new PathNotFoundException('Path "' . $path . '" not found');
110
    }
111
112
    /**
113
     * @param $parameterIn
114
     * @param $parameters
115
     * @param $arguments
116
     * @throws \ByJG\Swagger\Exception\NotMatchedException
117
     */
118
    private function validateArguments($parameterIn, $parameters, $arguments)
119
    {
120
        if ($this->getSpecificationVersion() === '3') {
121
            foreach ($parameters as $parameter) {
122
                if ($parameter['schema']['type'] === "integer"
123
                    && filter_var($arguments[$parameter['name']], FILTER_VALIDATE_INT) === false) {
124
                    throw new NotMatchedException('Path expected an integer value');
125
                }
126
            }
127
            return;
128
        }
129
130
        foreach ($parameters as $parameter) {
131
            if ($parameter['in'] === $parameterIn
132
                && $parameter['type'] === "integer"
133
                && filter_var($arguments[$parameter['name']], FILTER_VALIDATE_INT) === false) {
134
                throw new NotMatchedException('Path expected an integer value');
135
            }
136
        }
137
    }
138
139
    /**
140
     * @param $name
141
     * @return mixed
142
     * @throws DefinitionNotFoundException
143
     * @throws InvalidDefinitionException
144
     */
145
    public function getDefintion($name)
146
    {
147
        $nameParts = explode('/', $name);
148
149
        if ($this->getSpecificationVersion() === '3') {
150 View Code Duplication
            if (count($nameParts) < 4 || $nameParts[0] !== '#') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
151
                throw new InvalidDefinitionException('Invalid Component');
152
            }
153
154 View Code Duplication
            if (!isset($this->jsonFile[$nameParts[1]][$nameParts[2]][$nameParts[3]])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
155
                throw new DefinitionNotFoundException("Component'$name' not found");
156
            }
157
158
            return $this->jsonFile[$nameParts[1]][$nameParts[2]][$nameParts[3]];
159
        }
160
161 View Code Duplication
        if (count($nameParts) < 3 || $nameParts[0] !== '#') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
162
            throw new InvalidDefinitionException('Invalid Definition');
163
        }
164
165 View Code Duplication
        if (!isset($this->jsonFile[$nameParts[1]][$nameParts[2]])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
166
            throw new DefinitionNotFoundException("Definition '$name' not found");
167
        }
168
169
        return $this->jsonFile[$nameParts[1]][$nameParts[2]];
170
    }
171
172
    /**
173
     * @param $path
174
     * @param $method
175
     * @return \ByJG\Swagger\SwaggerRequestBody
176
     * @throws \ByJG\Swagger\Exception\HttpMethodNotFoundException
177
     * @throws \ByJG\Swagger\Exception\NotMatchedException
178
     * @throws \ByJG\Swagger\Exception\PathNotFoundException
179
     */
180
    public function getRequestParameters($path, $method)
181
    {
182
        $structure = $this->getPathDefinition($path, $method);
183
184
        if($this->getSpecificationVersion() === '3') {
185
            if (!isset($structure['requestBody'])) {
186
                return new SwaggerRequestBody($this, "$method $path", []);
187
            }
188
            return new SwaggerRequestBody($this, "$method $path", $structure['requestBody']);
189
        }
190
191
        if (!isset($structure[self::SWAGGER_PARAMETERS])) {
192
            return new SwaggerRequestBody($this, "$method $path", []);
193
        }
194
        return new SwaggerRequestBody($this, "$method $path", $structure[self::SWAGGER_PARAMETERS]);
195
    }
196
197
    /**
198
     * @param $path
199
     * @param $method
200
     * @param $status
201
     * @return \ByJG\Swagger\SwaggerResponseBody
202
     * @throws \ByJG\Swagger\Exception\HttpMethodNotFoundException
203
     * @throws \ByJG\Swagger\Exception\InvalidDefinitionException
204
     * @throws \ByJG\Swagger\Exception\NotMatchedException
205
     * @throws \ByJG\Swagger\Exception\PathNotFoundException
206
     */
207
    public function getResponseParameters($path, $method, $status)
208
    {
209
        $structure = $this->getPathDefinition($path, $method);
210
211
        if (!isset($structure['responses'][$status])) {
212
            throw new InvalidDefinitionException("Could not found status code '$status' in '$path' and '$method'");
213
        }
214
215
        return new SwaggerResponseBody($this, "$method $status $path", $structure['responses'][$status]);
216
    }
217
218
    /**
219
     * OpenApi 2.0 doesn't describe null values, so this flag defines,
220
     * if match is ok when one of property
221
     *
222
     * @return bool
223
     */
224
    public function isAllowNullValues()
225
    {
226
        return $this->allowNullValues;
227
    }
228
229
    /**
230
     * OpenApi 2.0 doesn't describe null values, so this flag defines,
231
     * if match is ok when one of property
232
     *
233
     * @param $value
234
     */
235
    public function setAllowNullValues($value)
236
    {
237
        $this->allowNullValues = (bool) $value;
238
    }
239
}
240