Schema::getPathDefinition()   B
last analyzed

Complexity

Conditions 10
Paths 11

Size

Total Lines 52
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 27
c 1
b 0
f 0
dl 0
loc 52
rs 7.6666
cc 10
nc 11
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace ByJG\ApiTools\Base;
4
5
use ByJG\ApiTools\Exception\DefinitionNotFoundException;
6
use ByJG\ApiTools\Exception\HttpMethodNotFoundException;
7
use ByJG\ApiTools\Exception\InvalidDefinitionException;
8
use ByJG\ApiTools\Exception\InvalidRequestException;
9
use ByJG\ApiTools\Exception\NotMatchedException;
10
use ByJG\ApiTools\Exception\PathNotFoundException;
11
use ByJG\ApiTools\OpenApi\OpenApiSchema;
12
use ByJG\ApiTools\Swagger\SwaggerSchema;
13
use ByJG\Util\Uri;
14
use InvalidArgumentException;
15
16
abstract class Schema
17
{
18
    protected array $jsonFile;
19
    protected bool $allowNullValues = false;
20
    protected string $specificationVersion;
21
22
    const SWAGGER_PATHS = "paths";
23
    const SWAGGER_PARAMETERS = "parameters";
24
    const SWAGGER_COMPONENTS = "components";
25
26
    /**
27
     * Returns the major specification version
28
     * @return string
29
     */
30
    public function getSpecificationVersion(): string
31
    {
32
        return $this->specificationVersion;
33
    }
34
35
    /**
36
     * Factory function for schemata.
37
     *
38
     * Initialize with schema data, which can be a PHP array or encoded as JSON.
39
     * This determines the type of the schema from the given data.
40
     *
41
     * @param array|string $data
42
     * @param bool $extraArgs
43
     * @return Schema
44
     */
45
    public static function getInstance(array|string $data, bool $extraArgs = false): Schema
46
    {
47
        // when given a string, decode from JSON
48
        if (is_string($data)) {
0 ignored issues
show
introduced by
The condition is_string($data) is always false.
Loading history...
49
            $data = json_decode($data, true);
50
        }
51
        // check which type of file we got and dispatch to derived class constructor
52
        if (isset($data['swagger'])) {
53
            return new SwaggerSchema($data, $extraArgs);
54
        }
55
        if (isset($data['openapi'])) {
56
            return new OpenApiSchema($data);
57
        }
58
59
        throw new InvalidArgumentException('failed to determine schema type from data');
60
    }
61
62
    /**
63
     * @param string $path
64
     * @param string $method
65
     * @return mixed
66
     * @throws DefinitionNotFoundException
67
     * @throws HttpMethodNotFoundException
68
     * @throws InvalidDefinitionException
69
     * @throws InvalidRequestException
70
     * @throws NotMatchedException
71
     * @throws PathNotFoundException
72
     */
73
    public function getPathDefinition(string $path, string $method): mixed
74
    {
75
        $method = strtolower($method);
76
77
        $path = preg_replace('~^' . $this->getBasePath() . '~', '', $path);
78
79
        $uri = new Uri($path);
80
81
        // Try direct match
82
        if (isset($this->jsonFile[self::SWAGGER_PATHS][$uri->getPath()])) {
83
            if (isset($this->jsonFile[self::SWAGGER_PATHS][$uri->getPath()][$method])) {
84
                return $this->jsonFile[self::SWAGGER_PATHS][$uri->getPath()][$method];
85
            }
86
            throw new HttpMethodNotFoundException("The http method '$method' not found in '$path'");
87
        }
88
89
        // Try inline parameter
90
        foreach (array_keys($this->jsonFile[self::SWAGGER_PATHS]) as $pathItem) {
91
            if (!str_contains($pathItem, '{')) {
92
                continue;
93
            }
94
95
            $pathItemPattern = '~^' . preg_replace('~{(.*?)}~', '(?<\1>[^/]+)', $pathItem) . '$~';
96
97
            $matches = [];
98
            if (empty($uri->getPath())) {
99
                throw new InvalidRequestException('The path is empty');
100
            }
101
            if (preg_match($pathItemPattern, $uri->getPath(), $matches)) {
102
                $pathDef = $this->jsonFile[self::SWAGGER_PATHS][$pathItem];
103
                if (!isset($pathDef[$method])) {
104
                    throw new HttpMethodNotFoundException("The http method '$method' not found in '$path'");
105
                }
106
107
                $parametersPathMethod = [];
108
                $parametersPath = [];
109
110
                if (isset($pathDef[$method][self::SWAGGER_PARAMETERS])) {
111
                    $parametersPathMethod = $pathDef[$method][self::SWAGGER_PARAMETERS];
112
                }
113
114
                if (isset($pathDef[self::SWAGGER_PARAMETERS])) {
115
                    $parametersPath = $pathDef[self::SWAGGER_PARAMETERS];
116
                }
117
118
                $this->validateArguments('path', array_merge($parametersPathMethod, $parametersPath), $matches);
119
120
                return $pathDef[$method];
121
            }
122
        }
123
124
        throw new PathNotFoundException('Path "' . $path . '" not found');
125
    }
126
127
    /**
128
     * @param string $path
129
     * @param string $method
130
     * @param int $status
131
     * @return Body
132
     * @throws DefinitionNotFoundException
133
     * @throws HttpMethodNotFoundException
134
     * @throws InvalidDefinitionException
135
     * @throws InvalidRequestException
136
     * @throws NotMatchedException
137
     * @throws PathNotFoundException
138
     */
139
    public function getResponseParameters(string $path, string $method, int $status): Body
140
    {
141
        $structure = $this->getPathDefinition($path, $method);
142
143
        if (!isset($structure['responses']["200"])) {
144
            $structure['responses']["200"] = ["description" => "Auto Generated OK"];
145
        }
146
147
        $verifyStatus = $status;
148
        if (!isset($structure['responses'][$verifyStatus])) {
149
            $verifyStatus = 'default';
150
            if (!isset($structure['responses'][$verifyStatus])) {
151
                throw new InvalidDefinitionException("Could not found status code '$status' in '$path' and '$method'");
152
            }
153
        }
154
155
        return $this->getResponseBody($this, "$method $status $path", $structure['responses'][$verifyStatus]);
156
    }
157
158
    /**
159
     * OpenApi 2.0 doesn't describe null values, so this flag defines,
160
     * if match is ok when one of property
161
     *
162
     * @return bool
163
     */
164
    public function isAllowNullValues(): bool
165
    {
166
        return $this->allowNullValues;
167
    }
168
169
    /**
170
     * @return string
171
     */
172
    abstract public function getServerUrl(): string;
173
174
    /**
175
     * @param string $parameterIn
176
     * @param array $parameters
177
     * @param array $arguments
178
     * @throws DefinitionNotFoundException
179
     * @throws InvalidDefinitionException
180
     * @throws NotMatchedException
181
     */
182
    abstract protected function validateArguments(string $parameterIn, array $parameters, array $arguments): void;
183
184
    abstract public function getBasePath(): string;
185
186
    /**
187
     * @param $name
188
     * @return mixed
189
     * @throws DefinitionNotFoundException
190
     * @throws InvalidDefinitionException
191
     */
192
    abstract public function getDefinition($name): mixed;
193
194
    /**
195
     * @param string $path
196
     * @param string $method
197
     * @return Body
198
     * @throws HttpMethodNotFoundException
199
     * @throws PathNotFoundException
200
     * @throws DefinitionNotFoundException
201
     * @throws HttpMethodNotFoundException
202
     * @throws InvalidDefinitionException
203
     * @throws NotMatchedException
204
     * @throws PathNotFoundException
205
     */
206
    abstract public function getRequestParameters(string $path, string $method): Body;
207
208
    /**
209
     * @param Schema $schema
210
     * @param string $name
211
     * @param array $structure
212
     * @param bool $allowNullValues
213
     * @return Body
214
     */
215
    abstract public function getResponseBody(Schema $schema, string $name, array $structure, bool $allowNullValues = false): Body;
216
}
217