Skip to content

Commit d6f7c59

Browse files
committed
OpenAPI: Make sure we do not override defined parameters #4137
1 parent 8b02b2b commit d6f7c59

File tree

2 files changed

+50
-8
lines changed

2 files changed

+50
-8
lines changed

src/OpenApi/Factory/OpenApiFactory.php

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,19 +175,42 @@ private function collectPaths(ResourceMetadata $resourceMetadata, string $resour
175175
// Set up parameters
176176
if (OperationType::ITEM === $operationType) {
177177
foreach ($identifiers as $parameterName => $identifier) {
178-
$parameters[] = new Model\Parameter(\is_string($parameterName) ? $parameterName : $identifier, 'path', 'Resource identifier', true, false, false, ['type' => 'string']);
178+
$parameterName = \is_string($parameterName) ? $parameterName : $identifier;
179+
$parameter = new Model\Parameter($parameterName, 'path', 'Resource identifier', true, false, false, ['type' => 'string']);
180+
if ($this->hasParameter($parameter, $parameters)) {
181+
continue;
182+
}
183+
184+
$parameters[] = $parameter;
179185
}
180186
$links[$operationId] = $this->getLink($resourceClass, $operationId, $path);
181187
} elseif (OperationType::COLLECTION === $operationType && 'GET' === $method) {
182-
$parameters = array_merge($parameters, $this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($resourceMetadata, $operationName, $resourceClass));
188+
foreach (array_merge($this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($resourceMetadata, $operationName, $resourceClass)) as $parameter) {
189+
if ($this->hasParameter($parameter, $parameters)) {
190+
continue;
191+
}
192+
193+
$parameters[] = $parameter;
194+
}
183195
} elseif (OperationType::SUBRESOURCE === $operationType) {
184196
foreach ($operation['identifiers'] as $parameterName => [$class, $property]) {
185-
$parameters[] = new Model\Parameter($parameterName, 'path', $this->resourceMetadataFactory->create($class)->getShortName().' identifier', true, false, false, ['type' => 'string']);
197+
$parameter = new Model\Parameter($parameterName, 'path', $this->resourceMetadataFactory->create($class)->getShortName().' identifier', true, false, false, ['type' => 'string']);
198+
if ($this->hasParameter($parameter, $parameters)) {
199+
continue;
200+
}
201+
202+
$parameters[] = $parameter;
186203
}
187204

188205
if ($operation['collection']) {
189206
$subresourceMetadata = $this->resourceMetadataFactory->create($resourceClass);
190-
$parameters = array_merge($parameters, $this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($subresourceMetadata, $operationName, $resourceClass));
207+
foreach (array_merge($this->getPaginationParameters($resourceMetadata, $operationName), $this->getFiltersParameters($subresourceMetadata, $operationName, $resourceClass)) as $parameter) {
208+
if ($this->hasParameter($parameter, $parameters)) {
209+
continue;
210+
}
211+
212+
$parameters[] = $parameter;
213+
}
191214
}
192215
}
193216

@@ -486,4 +509,18 @@ private function getSecuritySchemes(): array
486509

487510
return $securitySchemes;
488511
}
512+
513+
/**
514+
* @var Model\Parameter[]
515+
*/
516+
private function hasParameter(Model\Parameter $parameter, array $parameters): bool
517+
{
518+
foreach ($parameters as $existingParameter) {
519+
if ($existingParameter->getName() === $parameter->getName() && $existingParameter->getIn() === $parameter->getIn()) {
520+
return true;
521+
}
522+
}
523+
524+
return false;
525+
}
489526
}

tests/OpenApi/Factory/OpenApiFactoryTest.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ public function testInvoke(): void
7777
'custom' => ['method' => 'HEAD', 'path' => '/foo/{id}', 'openapi_context' => [
7878
'description' => 'Custom description',
7979
'parameters' => [
80-
['description' => 'Test parameter', 'name' => 'param', 'in' => 'path', 'type' => 'string', 'required' => true, 'default' => 'BOTH'],
80+
['description' => 'Test parameter', 'name' => 'param', 'in' => 'path', 'required' => true],
81+
['description' => 'Replace parameter', 'name' => 'id', 'in' => 'path', 'required' => true, 'schema' => ['type' => 'string', 'format' => 'uuid']],
8182
],
8283
'tags' => ['Dummy', 'Profile'],
8384
'responses' => [
@@ -117,7 +118,11 @@ public function testInvoke(): void
117118
'formats' => ['method' => 'PUT', 'path' => '/formatted/{id}', 'output_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']], 'input_formats' => ['json' => ['application/json'], 'csv' => ['text/csv']]],
118119
],
119120
[
120-
'get' => ['method' => 'GET'] + self::OPERATION_FORMATS,
121+
'get' => ['method' => 'GET', 'openapi_context' => [
122+
'parameters' => [
123+
['description' => 'Test modified collection page number', 'name' => 'page', 'in' => 'query', 'required' => false, 'schema' => ['type' => 'integer', 'default' => 1], 'allowEmptyValue' => true],
124+
],
125+
]] + self::OPERATION_FORMATS,
121126
'post' => ['method' => 'POST'] + self::OPERATION_FORMATS,
122127
'filtered' => ['method' => 'GET', 'filters' => ['f1', 'f2', 'f3', 'f4', 'f5'], 'path' => '/filtered'] + self::OPERATION_FORMATS,
123128
'paginated' => ['method' => 'GET', 'pagination_client_enabled' => true, 'pagination_client_items_per_page' => true, 'pagination_items_per_page' => 20, 'pagination_maximum_items_per_page' => 80, 'path' => '/paginated'] + self::OPERATION_FORMATS,
@@ -306,7 +311,7 @@ public function testInvoke(): void
306311
'Retrieves the collection of Dummy resources.',
307312
null,
308313
[
309-
new Model\Parameter('page', 'query', 'The collection page number', false, false, true, [
314+
new Model\Parameter('page', 'query', 'Test modified collection page number', false, false, true, [
310315
'type' => 'integer',
311316
'default' => 1,
312317
]),
@@ -434,7 +439,7 @@ public function testInvoke(): void
434439
'Dummy',
435440
'Custom description',
436441
null,
437-
[new Model\Parameter('param', 'path', 'Test parameter', true), new Model\Parameter('id', 'path', 'Resource identifier', true, false, false, ['type' => 'string'])],
442+
[new Model\Parameter('param', 'path', 'Test parameter', true), new Model\Parameter('id', 'path', 'Replace parameter', true, false, false, ['type' => 'string', 'format' => 'uuid'])],
438443
new Model\RequestBody('Custom request body', new \ArrayObject([
439444
'multipart/form-data' => [
440445
'schema' => [

0 commit comments

Comments
 (0)