Skip to content

Commit 04f8855

Browse files
committed
Merge branches 'master' and '84-validate-returns-true-with-wrong-top-level-elements' of github.com:SOHELAHMED7/php-openapi into 84-validate-returns-true-with-wrong-top-level-elements
2 parents 3008e66 + 893ab10 commit 04f8855

19 files changed

+698
-21
lines changed

Makefile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ fix-style: php-cs-fixer.phar
3737
$(DOCKER_PHP) vendor/bin/indent --spaces .php_cs.dist
3838
$(DOCKER_PHP) ./php-cs-fixer.phar fix src/ --diff
3939

40-
install:
40+
cli:
41+
docker-compose run --rm php bash
42+
43+
install: composer.json package.json
4144
$(DOCKER_PHP) composer install --prefer-dist --no-interaction --no-progress --ansi
4245
$(DOCKER_NODE) yarn install
4346

@@ -82,4 +85,3 @@ coverage: .php-openapi-covA .php-openapi-covB
8285
grep -rhPo '^class \w+' src/spec/ | awk '{print $$2}' |grep -v '^Type$$' | sort > $@
8386

8487
.PHONY: all check-style fix-style install test lint coverage
85-

bin/php-openapi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ switch ($command) {
215215

216216
if ($outputFile === null) {
217217
if ($outputFormat === null) {
218-
error("No output fromat specified, please specify --write-json or --write-yaml.", "usage");
218+
error("No output format specified, please specify --write-json or --write-yaml.", "usage");
219219
} elseif ($outputFormat === 'json') {
220220
fwrite(STDOUT, \cebe\openapi\Writer::writeToJson($openApi));
221221
} else {

src/ReferenceContext.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,18 @@ private function reduceDots($path)
121121
unset($parts[$i]);
122122
continue;
123123
}
124-
if ($i > 0 && $parts[$i] === '..' && $parts[$i - $parentOffset] !== '..') {
125-
unset($parts[$i - $parentOffset]);
124+
125+
if ($i > 0 && $parts[$i] === '..') {
126+
$parent = $i - $parentOffset;
127+
//Make sure parent exists, if not, check the next parent etc
128+
while ($parent >= 0 && empty($parts[$parent])) {
129+
$parent--;
130+
}
131+
//Confirm parent is valid
132+
if (!empty($parts[$parent]) && $parts[$parent] !== '..') {
133+
unset($parts[$parent]);
134+
}
126135
unset($parts[$i]);
127-
$parentOffset += 2;
128136
}
129137
}
130138
return '/'.implode('/', $parts);

src/spec/OpenApi.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ protected function attributes(): array
3737
'servers' => [Server::class],
3838
'paths' => Paths::class,
3939
'components' => Components::class,
40-
'security' => [SecurityRequirement::class],
40+
'security' => SecurityRequirements::class,
4141
'tags' => [Tag::class],
4242
'externalDocs' => ExternalDocumentation::class,
4343
];

src/spec/Operation.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected function attributes(): array
4646
'responses' => Responses::class,
4747
'callbacks' => [Type::STRING, Callback::class],
4848
'deprecated' => Type::BOOLEAN,
49-
'security' => [SecurityRequirement::class],
49+
'security' => SecurityRequirements::class,
5050
'servers' => [Server::class],
5151
];
5252
}

src/spec/PathItem.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public function resolveReferences(ReferenceContext $context = null)
180180
foreach ($this->$attribute as $k => $item) {
181181
if ($item instanceof Reference) {
182182
$referencedObject = $item->resolve();
183-
$this->$attribute = [$k => $referencedObject] + $this->$attribute;
183+
$this->$attribute = $this->$attribute + [$k => $referencedObject];
184184
if (!$referencedObject instanceof Reference && $referencedObject !== null) {
185185
$referencedObject->resolveReferences();
186186
}

src/spec/SecurityRequirement.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@
1010
use cebe\openapi\SpecBaseObject;
1111

1212
/**
13-
* Lists the required security schemes to execute this operation.
13+
* A required security scheme to execute this operation.
1414
*
1515
* @link https://github.com/OAI/OpenAPI-Specification/blob/3.0.2/versions/3.0.2.md#securityRequirementObject
1616
*
1717
*/
1818
class SecurityRequirement extends SpecBaseObject
1919
{
20+
private $_securityRequirement;
21+
public function __construct(array $data)
22+
{
23+
parent::__construct($data);
24+
$this->_securityRequirement = $data;
25+
}
26+
2027
/**
2128
* @return array array of attributes available in this object.
2229
*/
@@ -34,4 +41,9 @@ protected function attributes(): array
3441
protected function performValidation()
3542
{
3643
}
44+
45+
public function getSerializableData()
46+
{
47+
return $this->_securityRequirement;
48+
}
3749
}

src/spec/SecurityRequirements.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (c) 2018 Carsten Brandt <[email protected]> and contributors
5+
* @license https://github.com/cebe/php-openapi/blob/master/LICENSE
6+
*/
7+
8+
namespace cebe\openapi\spec;
9+
10+
use cebe\openapi\SpecBaseObject;
11+
12+
/**
13+
* Lists the required security schemes to execute this operation.
14+
*
15+
* @link https://github.com/OAI/OpenAPI-Specification/blob/3.0.2/versions/3.0.2.md#securityRequirementObject
16+
*
17+
*/
18+
class SecurityRequirements extends SpecBaseObject
19+
{
20+
private $_securityRequirements;
21+
22+
public function __construct(array $data)
23+
{
24+
parent::__construct($data);
25+
26+
foreach ($data as $index => $value) {
27+
if (is_numeric($index)) { // read
28+
$this->_securityRequirements[array_keys($value)[0]] = new SecurityRequirement(array_values($value)[0]);
29+
} else { // write
30+
$this->_securityRequirements[$index] = $value;
31+
}
32+
}
33+
if ($data === []) {
34+
$this->_securityRequirements = [];
35+
}
36+
}
37+
38+
/**
39+
* @return array array of attributes available in this object.
40+
*/
41+
protected function attributes(): array
42+
{
43+
// this object does not have a fixed set of attribute names
44+
return [];
45+
}
46+
47+
/**
48+
* Perform validation on this object, check data against OpenAPI Specification rules.
49+
*
50+
* Call `addError()` in case of validation errors.
51+
*/
52+
protected function performValidation()
53+
{
54+
}
55+
56+
/**
57+
* {@inheritDoc}
58+
*/
59+
public function getSerializableData()
60+
{
61+
$data = [];
62+
foreach ($this->_securityRequirements ?? [] as $name => $securityRequirement) {
63+
/** @var SecurityRequirement $securityRequirement */
64+
$data[] = [$name => $securityRequirement->getSerializableData()];
65+
}
66+
return $data;
67+
}
68+
69+
public function getRequirement(string $name)
70+
{
71+
return $this->_securityRequirements[$name] ?? null;
72+
}
73+
74+
public function getRequirements()
75+
{
76+
return $this->_securityRequirements;
77+
}
78+
}

tests/ReferenceContextTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,22 @@ public function normalizeUriProvider()
179179
'/var/www/api/../definitions.yaml',
180180
'file:///var/www/definitions.yaml',
181181
],
182+
[
183+
'/./definitions.yaml',
184+
'file:///definitions.yaml',
185+
],
186+
[
187+
'/var/www/api/schema/../../definitions.yaml',
188+
'file:///var/www/definitions.yaml',
189+
],
190+
[
191+
'/var/www/api/schema/./../data/./../definitions.yaml',
192+
'file:///var/www/api/definitions.yaml',
193+
],
194+
[
195+
'/var/www/api/schema/./../definitions.yaml',
196+
'file:///var/www/api/definitions.yaml',
197+
],
182198
[
183199
'/var/www/api/../definitions.yaml#/components/Pet',
184200
'file:///var/www/definitions.yaml#/components/Pet',

tests/WriterTest.php

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
<?php
22

3+
use cebe\openapi\spec\Components;
4+
use cebe\openapi\spec\Operation;
5+
use cebe\openapi\spec\PathItem;
6+
use cebe\openapi\spec\Response;
7+
use cebe\openapi\spec\Responses;
38
use cebe\openapi\spec\SecurityRequirement;
9+
use cebe\openapi\spec\SecurityRequirements;
10+
use cebe\openapi\spec\SecurityScheme;
411

512
class WriterTest extends \PHPUnit\Framework\TestCase
613
{
@@ -137,7 +144,9 @@ public function testWriteEmptySecurityYaml()
137144
public function testWriteEmptySecurityPartJson()
138145
{
139146
$openapi = $this->createOpenAPI([
140-
'security' => [new SecurityRequirement(['Bearer' => []])],
147+
'security' => new SecurityRequirements([
148+
'Bearer' => new SecurityRequirement([])
149+
]),
141150
]);
142151

143152
$json = \cebe\openapi\Writer::writeToJson($openapi);
@@ -166,7 +175,9 @@ public function testWriteEmptySecurityPartJson()
166175
public function testWriteEmptySecurityPartYaml()
167176
{
168177
$openapi = $this->createOpenAPI([
169-
'security' => [new SecurityRequirement(['Bearer' => []])],
178+
'security' => new SecurityRequirements([
179+
'Bearer' => new SecurityRequirement([])
180+
]),
170181
]);
171182

172183
$yaml = \cebe\openapi\Writer::writeToYaml($openapi);
@@ -182,6 +193,105 @@ public function testWriteEmptySecurityPartYaml()
182193
-
183194
Bearer: []
184195
196+
YAML
197+
),
198+
$yaml
199+
);
200+
}
201+
202+
public function testSecurityAtPathOperationLevel()
203+
{
204+
$openapi = $this->createOpenAPI([
205+
'components' => new Components([
206+
'securitySchemes' => [
207+
'BearerAuth' => new SecurityScheme([
208+
'type' => 'http',
209+
'scheme' => 'bearer',
210+
'bearerFormat' => 'AuthToken and JWT Format' # optional, arbitrary value for documentation purposes
211+
]),
212+
],
213+
]),
214+
'paths' => [
215+
'/test' => new PathItem([
216+
'get' => new Operation([
217+
'security' => new SecurityRequirements([
218+
'BearerAuth' => new SecurityRequirement([]),
219+
]),
220+
'responses' => new Responses([
221+
200 => new Response(['description' => 'OK']),
222+
])
223+
])
224+
])
225+
]
226+
]);
227+
228+
$yaml = \cebe\openapi\Writer::writeToYaml($openapi);
229+
230+
231+
$this->assertEquals(preg_replace('~\R~', "\n", <<<YAML
232+
openapi: 3.0.0
233+
info:
234+
title: 'Test API'
235+
version: 1.0.0
236+
paths:
237+
/test:
238+
get:
239+
responses:
240+
'200':
241+
description: OK
242+
security:
243+
-
244+
BearerAuth: []
245+
components:
246+
securitySchemes:
247+
BearerAuth:
248+
type: http
249+
scheme: bearer
250+
bearerFormat: 'AuthToken and JWT Format'
251+
252+
YAML
253+
),
254+
$yaml
255+
);
256+
}
257+
258+
public function testSecurityAtGlobalLevel()
259+
{
260+
$openapi = $this->createOpenAPI([
261+
'components' => new Components([
262+
'securitySchemes' => [
263+
'BearerAuth' => new SecurityScheme([
264+
'type' => 'http',
265+
'scheme' => 'bearer',
266+
'bearerFormat' => 'AuthToken and JWT Format' # optional, arbitrary value for documentation purposes
267+
])
268+
],
269+
]),
270+
'security' => new SecurityRequirements([
271+
'BearerAuth' => new SecurityRequirement([])
272+
]),
273+
'paths' => [],
274+
]);
275+
276+
$yaml = \cebe\openapi\Writer::writeToYaml($openapi);
277+
278+
279+
$this->assertEquals(preg_replace('~\R~', "\n", <<<YAML
280+
openapi: 3.0.0
281+
info:
282+
title: 'Test API'
283+
version: 1.0.0
284+
paths: { }
285+
components:
286+
securitySchemes:
287+
BearerAuth:
288+
type: http
289+
scheme: bearer
290+
bearerFormat: 'AuthToken and JWT Format'
291+
security:
292+
-
293+
BearerAuth: []
294+
185295
YAML
186296
),
187297
$yaml

0 commit comments

Comments
 (0)