Skip to content

Commit 7b5f3da

Browse files
committed
1 parent 6d5bde9 commit 7b5f3da

File tree

3 files changed

+97
-22
lines changed

3 files changed

+97
-22
lines changed

src/spec/SecurityRequirements.php

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@ public function __construct(array $data)
2424
parent::__construct($data);
2525

2626
foreach ($data as $index => $value) {
27-
if (is_numeric($index)) { // read
28-
if ($value === []) { # empty Security Requirement Object (`{}`) = anonymous access https://github.com/cebe/php-openapi/issues/238
29-
$this->_securityRequirements[$index] = $value;
30-
} else {
31-
$this->_securityRequirements[array_keys($value)[0]] = new SecurityRequirement(array_values($value)[0]);
27+
if (is_numeric($index) && $value === []) { # empty Security Requirement Object (`{}`) = anonymous access
28+
$this->_securityRequirements[$index] = [];
29+
continue;
30+
}
31+
32+
if (is_string($index)) {
33+
$this->_securityRequirements[] = [$index => $value instanceof SecurityRequirement ? $value : new SecurityRequirement($value)];
34+
} elseif (is_numeric($index)) {
35+
foreach ($value as $innerIndex => $subValue) {
36+
$this->_securityRequirements[$index][$innerIndex] = $subValue instanceof SecurityRequirement ? $subValue : new SecurityRequirement($subValue);
3237
}
33-
} else { // write
34-
$this->_securityRequirements[$index] = $value;
3538
}
3639
}
3740

@@ -64,25 +67,51 @@ protected function performValidation()
6467
public function getSerializableData()
6568
{
6669
$data = [];
67-
foreach ($this->_securityRequirements ?? [] as $name => $securityRequirement) {
68-
/** @var SecurityRequirement $securityRequirement */
6970

70-
if (is_numeric($name)) {
71-
$data[$name] = (object) $securityRequirement; # case https://github.com/cebe/php-openapi/issues/238
72-
} else {
73-
$data[] = (object) [$name => $securityRequirement->getSerializableData()];
71+
foreach ($this->_securityRequirements ?? [] as $outerIndex => $content) {
72+
73+
if (is_string($outerIndex)) {
74+
$data[] = [$outerIndex => $content->getSerializableData()];
75+
} elseif (is_numeric($outerIndex)) {
76+
if ($content === []) {
77+
$data[$outerIndex] = (object)$content;
78+
continue;
79+
}
80+
$innerResult = [];
81+
foreach ($content as $innerIndex => $innerContent) {
82+
$result = is_object($innerContent) && method_exists($innerContent, 'getSerializableData') ? $innerContent->getSerializableData() : $innerContent;
83+
$innerResult[$innerIndex] = $result;
84+
}
85+
$data[$outerIndex] = (object)$innerResult;
7486
}
7587
}
7688
return $data;
7789
}
7890

7991
public function getRequirement(string $name)
8092
{
81-
return $this->_securityRequirements[$name] ?? null;
93+
return static::searchKey($this->_securityRequirements, $name);
8294
}
8395

8496
public function getRequirements()
8597
{
8698
return $this->_securityRequirements;
8799
}
100+
101+
private static function searchKey(array $array, string $searchKey)
102+
{
103+
foreach ($array as $key => $value) {
104+
if ($key === $searchKey) {
105+
return $value;
106+
}
107+
if (is_array($value)) {
108+
$mt = __METHOD__;
109+
$result = $mt($value, $searchKey);
110+
if ($result !== null) {
111+
return $result; // key found in deeply nested/associative array
112+
}
113+
}
114+
}
115+
return null; // key not found
116+
}
88117
}

tests/data/issue/242/spec2.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
openapi: 3.0.0
2+
info:
3+
title: API Documentation
4+
description: All API endpoints are presented here.
5+
version: 1.0.0
6+
servers:
7+
- url: http://127.0.0.1:8080/
8+
9+
paths:
10+
11+
/endpoint:
12+
get:
13+
responses:
14+
'200':
15+
description: OK
16+
security:
17+
- apiKey: []
18+
bearerAuth: []
19+
components:
20+
securitySchemes:
21+
apiKey:
22+
type: apiKey
23+
in: header
24+
name: X-APi-Key
25+
bearerAuth:
26+
type: http
27+
scheme: bearer
28+
bearerFormat: JWT
29+
description: JWT Authorization header using the Bearer scheme.
30+

tests/issues/242/Issue242Test.php

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
<?php
22

33
use cebe\openapi\Reader;
4-
use cebe\openapi\spec\OpenApi;
5-
use cebe\openapi\spec\SecurityRequirements;
6-
use cebe\openapi\Writer;
4+
use cebe\openapi\SpecObjectInterface;
5+
use PHPUnit\Framework\TestCase;
76

87
// https://github.com/cebe/php-openapi/issues/242
9-
class Issue242Test extends \PHPUnit\Framework\TestCase
8+
class Issue242Test extends TestCase
109
{
1110
public function test242CliCallToOpenapiSpecWithSecurityInPathFails()
1211
{
13-
$openapi = Reader::readFromJsonFile(dirname(__DIR__, 2) . '/data/issue/242/spec.json');
14-
$this->assertInstanceOf(\cebe\openapi\SpecObjectInterface::class, $openapi);
15-
1612
$file = dirname(__DIR__, 2) . '/data/issue/242/spec.json';
13+
$openapi = Reader::readFromJsonFile($file);
14+
$this->assertInstanceOf(SpecObjectInterface::class, $openapi);
15+
1716
$dirSep = DIRECTORY_SEPARATOR;
1817
$cmd = 'php ' . dirname(__DIR__, 3) . "{$dirSep}bin{$dirSep}php-openapi validate " . $file . " 2>&1";
1918
exec($cmd, $op, $ec);
@@ -26,4 +25,21 @@ private function removeCliFormatting($string)
2625
// Regex to remove ANSI escape codes
2726
return preg_replace('/\e\[[0-9;]*m/', '', $string);
2827
}
29-
}
28+
29+
public function test242Case2()
30+
{
31+
// read in yml
32+
$openapi = Reader::readFromYamlFile(dirname(__DIR__, 2) . '/data/issue/242/spec2.yml');
33+
$this->assertInstanceOf(SpecObjectInterface::class, $openapi);
34+
$this->assertSame(json_decode(json_encode($openapi->paths['/endpoint']->get->security->getSerializableData()), true), [
35+
[
36+
'apiKey' => [],
37+
'bearerAuth' => []
38+
]
39+
]);
40+
41+
// write in yml # TODO
42+
// read in json # TODO
43+
// write in json # TODO
44+
}
45+
}

0 commit comments

Comments
 (0)