Passed
Pull Request — master (#33)
by Joao
08:26
created

Schema::validateArguments()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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