Skip to content

Fix: Referenced Parameters compiling to Object instead of Array #234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c843243
Added test to confirm referenced parameters are compiling to arrays
Aribros Sep 13, 2023
db98ac8
Merge branch '155-referenced-parameters-compilng-to-object' of https:…
SOHELAHMED7 Apr 25, 2025
9acecc8
Failing test
SOHELAHMED7 Apr 25, 2025
3ab78b6
Original compiled file
SOHELAHMED7 Apr 26, 2025
a946647
Fix typo
SOHELAHMED7 Apr 29, 2025
aaff771
Fix this issue
SOHELAHMED7 Apr 30, 2025
e02cce1
Fix this issue in more proper way
SOHELAHMED7 Apr 30, 2025
e8b8b2e
Fix failing test
SOHELAHMED7 Apr 30, 2025
9dfa3e8
Fix failing test 2
SOHELAHMED7 Apr 30, 2025
f0a27b7
Add more assertions
SOHELAHMED7 Apr 30, 2025
02b63bd
Fix issue in Github action
SOHELAHMED7 Apr 30, 2025
61fe216
Fix issue in Github action for Windows
SOHELAHMED7 Apr 30, 2025
2e89e6a
Fix issue in Github action 2 - related to different symfony/yaml version
SOHELAHMED7 Apr 30, 2025
e04fc83
Fix issue in Github action 3 - related to different symfony/yaml version
SOHELAHMED7 Apr 30, 2025
b12c746
Fix issue in Github action 4 - related to different symfony/yaml version
SOHELAHMED7 Apr 30, 2025
db60bff
Fix issue in Github action 5 - related to different symfony/yaml version
SOHELAHMED7 Apr 30, 2025
7f34a3b
Fix issue in Github action 6 - related to different symfony/yaml version
SOHELAHMED7 Apr 30, 2025
e05cbd0
Fix issue in Github action 7 - related to different symfony/yaml version
SOHELAHMED7 May 2, 2025
9811689
Fix issue in Github action 8 - related to different symfony/yaml version
SOHELAHMED7 May 2, 2025
7e721bf
Fix issue in Github action 9 - related to different symfony/yaml version
SOHELAHMED7 May 2, 2025
241c469
Fix test on Windows
SOHELAHMED7 May 2, 2025
1e379ae
Fix test on Windows 2
SOHELAHMED7 May 3, 2025
5bebb98
Fix test related to line ending
SOHELAHMED7 May 3, 2025
1da45e9
Fix test related to line ending 2
SOHELAHMED7 May 3, 2025
c7a965f
Fix test related to line ending 3
SOHELAHMED7 May 3, 2025
6947e24
Revert "Fix test related to line ending 3"
SOHELAHMED7 May 3, 2025
20016f2
Check
SOHELAHMED7 May 3, 2025
f4628b0
Fix line ending issue in Windows - 4
SOHELAHMED7 May 3, 2025
8a41d74
Fix line ending issue in Windows - 5
SOHELAHMED7 May 3, 2025
ebeffc6
Cleanup
SOHELAHMED7 May 3, 2025
50fc31e
Change visibility
SOHELAHMED7 May 3, 2025
a38d47e
Test
SOHELAHMED7 May 3, 2025
eeb37f0
Cleanup
SOHELAHMED7 May 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/php-openapi
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ switch ($command) {

if ($outputFile === null) {
if ($outputFormat === null) {
error("No output fromat specified, please specify --write-json or --write-yaml.", "usage");
error("No output format specified, please specify --write-json or --write-yaml.", "usage");
} elseif ($outputFormat === 'json') {
fwrite(STDOUT, \cebe\openapi\Writer::writeToJson($openApi));
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/spec/PathItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public function resolveReferences(ReferenceContext $context = null)
foreach ($this->$attribute as $k => $item) {
if ($item instanceof Reference) {
$referencedObject = $item->resolve();
$this->$attribute = [$k => $referencedObject] + $this->$attribute;
$this->$attribute = $this->$attribute + [$k => $referencedObject];
if (!$referencedObject instanceof Reference && $referencedObject !== null) {
$referencedObject->resolveReferences();
}
Expand Down
128 changes: 128 additions & 0 deletions tests/data/issue/155/compiled-symfony-6.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
openapi: 3.0.0
info:
title: 'Test REST API'
description: 'Specifications for the Test REST API.'
contact:
name: bplainia
email: [email protected]
version: '2021-05-18'
servers:
-
url: 'http://localhost:8000'
description: Test
paths:
'/v1/organizations/{organizationId}/user':
post:
tags:
- pets
summary: 'Creates a user'
requestBody:
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
required: true
responses:
'201':
description: Created
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
'400':
description: 'Bad Request'
'403':
description: Forbidden
security:
-
BearerAuth: []
parameters:
-
name: api-version
in: header
description: 'The API version'
required: false
schema:
type: string
format: date
example: '2021-05-18'
-
name: organizationId
in: path
description: 'The Organization ID'
required: true
schema:
type: string
format: uuid
'/v1/organizations/{organizationId}/user/{id}':
get:
summary: 'Gets a user'
responses:
'200':
description: 'A bar'
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
'400':
description: 'Bad Request'
'403':
description: Forbidden
'404':
description: 'Not Found'
security:
-
BearerAuth: []
parameters:
-
name: api-version
in: header
description: 'The API version'
required: false
schema:
type: string
format: date
example: '2021-05-18'
-
name: organizationId
in: path
description: 'The Organization ID'
required: true
schema:
type: string
format: uuid
-
name: id
in: path
description: 'User''s ID'
required: true
schema:
type: string
format: uuid
128 changes: 128 additions & 0 deletions tests/data/issue/155/compiled-symfony-7.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
openapi: 3.0.0
info:
title: 'Test REST API'
description: 'Specifications for the Test REST API.'
contact:
name: bplainia
email: [email protected]
version: '2021-05-18'
servers:
-
url: 'http://localhost:8000'
description: Test
paths:
'/v1/organizations/{organizationId}/user':
post:
tags:
- pets
summary: 'Creates a user'
requestBody:
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
required: true
responses:
'201':
description: Created
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
'400':
description: 'Bad Request'
'403':
description: Forbidden
security:
-
BearerAuth: []
parameters:
-
name: api-version
in: header
description: 'The API version'
required: false
schema:
type: string
format: date
example: '2021-05-18'
-
name: organizationId
in: path
description: 'The Organization ID'
required: true
schema:
type: string
format: uuid
'/v1/organizations/{organizationId}/user/{id}':
get:
summary: 'Gets a user'
responses:
'200':
description: 'A bar'
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
'400':
description: 'Bad Request'
'403':
description: Forbidden
'404':
description: 'Not Found'
security:
-
BearerAuth: []
parameters:
-
name: api-version
in: header
description: 'The API version'
required: false
schema:
type: string
format: date
example: '2021-05-18'
-
name: organizationId
in: path
description: 'The Organization ID'
required: true
schema:
type: string
format: uuid
-
name: id
in: path
description: "User's ID"
required: true
schema:
type: string
format: uuid
67 changes: 67 additions & 0 deletions tests/spec/PathTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,71 @@ public function testPathItemReference()
$this->assertEquals('A bar', $barPath->get->responses['200']->description);
$this->assertEquals('non-existing resource', $barPath->get->responses['404']->description);
}

public function testPathParametersAreArrays()
{
$file = __DIR__ . '/data/path-params/openapi.yaml';
/** @var $openapi \cebe\openapi\spec\OpenApi */
$openapi = Reader::readFromYamlFile($file, \cebe\openapi\spec\OpenApi::class, true);

$result = $openapi->validate();
$this->assertEquals([], $openapi->getErrors(), print_r($openapi->getErrors(), true));
$this->assertTrue($result);

$this->assertInstanceOf(Paths::class, $openapi->paths);
$this->assertSame(gettype($openapi->paths->getPaths()), 'array');
$this->assertInstanceOf(PathItem::class, $usersPath = $openapi->paths['/v1/organizations/{organizationId}/user']);
$this->assertInstanceOf(PathItem::class, $userIdPath = $openapi->paths['/v1/organizations/{organizationId}/user/{id}']);

$result = $usersPath->validate();
$this->assertTrue($result);
$this->assertSame(gettype($usersPath->parameters), 'array');
$this->assertInstanceOf(\cebe\openapi\spec\Parameter::class, $usersPath->parameters[0]);
$this->assertInstanceOf(\cebe\openapi\spec\Parameter::class, $usersPath->parameters[1]);
$this->assertEquals('api-version', $usersPath->parameters[0]->name);

$result = $userIdPath->validate();
$this->assertTrue($result);
$this->assertSame(gettype($userIdPath->parameters), 'array');
$this->assertInstanceOf(\cebe\openapi\spec\Parameter::class, $userIdPath->parameters[0]);
$this->assertInstanceOf(\cebe\openapi\spec\Parameter::class, $userIdPath->parameters[1]);
$this->assertEquals('id', $userIdPath->parameters[2]->name);

$dirSep = DIRECTORY_SEPARATOR;
$output = dirname(__DIR__) . $dirSep . 'compiled.yml';
shell_exec('php ' . dirname(__DIR__, 2) . "{$dirSep}bin{$dirSep}php-openapi inline " . $file . ' ' . $output);

$baseExpected = dirname(__DIR__)."{$dirSep}data{$dirSep}issue{$dirSep}155{$dirSep}";
$expected = $baseExpected.'compiled-symfony-7.yml';
$version = static::symfonyYamlVersion();
$majorVersion = explode('.', $version)[0];

if ($majorVersion == 6) {
$expected = $baseExpected."compiled-symfony-6.yml";
if (version_compare(PHP_VERSION, '8.1', '>=') && version_compare($version, '6.0.0', '!=')) {
$expected = $baseExpected."compiled-symfony-7.yml";
}
} elseif ($majorVersion == 5) {
$expected = $baseExpected."compiled-symfony-6.yml";
}
if (stripos(PHP_OS, 'WIN') === 0) { # fixes https://github.com/cebe/php-openapi/actions/runs/14808968938/job/41581244210
file_put_contents($expected, preg_replace('~\R~', "\n", file_get_contents($expected))); # not an ideal solution, can be refactored
}

$this->assertFileEquals($output, $expected);
unlink($output);
}

protected static function symfonyYamlVersion()
{
$package = 'symfony/yaml';
$installed = json_decode(file_get_contents(__DIR__ . '/../../composer.lock'), true);

foreach ($installed['packages'] as $pkg) {
if ($pkg['name'] === $package) {
return str_replace('v', '', $pkg['version']);
}
}
return '7.0.0';
}
}
28 changes: 28 additions & 0 deletions tests/spec/data/path-params/global.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
components:
parameters:
Version:
in: header
name: api-version
required: false
schema:
type: string
format: date
example: '2021-05-18'
description: The API version
OrganizationId:
in: path
name: organizationId
required: true
schema:
type: string
format: uuid
description: The Organization ID
responses:
BadRequest:
description: Bad Request
Forbidden:
description: Forbidden
NotFound:
description: Not Found
Success:
description: Success
18 changes: 18 additions & 0 deletions tests/spec/data/path-params/openapi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
openapi: 3.0.0
info:
version: "2021-05-18"
title: Test REST API
description: Specifications for the Test REST API.
contact:
name: bplainia
email: [email protected]

servers:
- url: 'http://localhost:8000'
description: 'Test'

paths:
/v1/organizations/{organizationId}/user:
$ref: 'user.yaml#/paths/Users'
/v1/organizations/{organizationId}/user/{id}:
$ref: 'user.yaml#/paths/UserId'
Loading