Skip to content

Commit 9f05487

Browse files
committed
fix(openapi): correct parameter name when QueryParameter remaps a filter property
When a QueryParameter uses `property` to remap a filter's property name (e.g. `order[sort_by]` mapped to property `rating`), OpenApiFactory used `str_replace(, , )` to rewrite the filter description key. Because both the description key (`order[rating]`) and the replacement key (`order[sort_by]`) share the `order[...]` wrapper, the naive str_replace produced `order[order[sort_by]]`. Fix: skip filter description entries that don't match the mapped property and use the QueryParameter key directly as the parameter name.
1 parent fe84af2 commit 9f05487

3 files changed

Lines changed: 33 additions & 1 deletion

File tree

src/OpenApi/Factory/OpenApiFactory.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,10 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
346346
if ($d = $filter->getDescription($entityClass)) {
347347
foreach ($d as $name => $description) {
348348
if ($prop = $p->getProperty()) {
349-
$name = str_replace($prop, $key, $name);
349+
if (($description['property'] ?? null) !== $prop) {
350+
continue;
351+
}
352+
$name = $key;
350353
}
351354

352355
$openapiParameters[] = $this->getFilterParameter($name, $description, $operation->getShortName(), $f);

tests/Fixtures/TestBundle/Entity/ProductWithQueryParameter.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
use ApiPlatform\Doctrine\Orm\Filter\ExactFilter;
1717
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
1818
use ApiPlatform\Doctrine\Orm\Filter\PartialSearchFilter;
19+
use ApiPlatform\Metadata\ApiFilter;
1920
use ApiPlatform\Metadata\ApiResource;
2021
use ApiPlatform\Metadata\GetCollection;
2122
use ApiPlatform\Metadata\QueryParameter;
2223
use Doctrine\DBAL\Types\Types;
2324
use Doctrine\ORM\Mapping as ORM;
2425

2526
#[ORM\Entity]
27+
#[ApiFilter(OrderFilter::class, alias: 'product_order_filter', properties: ['rating'])]
2628
#[ApiResource(
2729
operations: [
2830
new GetCollection(
@@ -46,6 +48,10 @@
4648
filter: new OrderFilter(),
4749
properties: ['rating']
4850
),
51+
'order[sort_by]' => new QueryParameter(
52+
filter: 'product_order_filter',
53+
property: 'rating',
54+
),
4955
'exactBrand' => new QueryParameter(
5056
filter: new ExactFilter(),
5157
property: 'brand',

tests/Functional/Parameters/DoctrineTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,4 +470,27 @@ public static function openApiParameterDocumentationProvider(): array
470470
],
471471
];
472472
}
473+
474+
public function testQueryParameterPropertyRemapOpenApiParameterName(): void
475+
{
476+
if ($this->isMongoDB()) {
477+
$this->markTestSkipped('Not tested with mongodb.');
478+
}
479+
480+
$resource = ProductWithQueryParameter::class;
481+
$this->recreateSchema([$resource]);
482+
483+
$response = self::createClient()->request('GET', '/docs', [
484+
'headers' => ['Accept' => 'application/vnd.openapi+json'],
485+
]);
486+
487+
$this->assertResponseIsSuccessful();
488+
$openApiDoc = $response->toArray();
489+
490+
$parameters = $openApiDoc['paths']['/product_with_query_parameters']['get']['parameters'];
491+
$parameterNames = array_column($parameters, 'name');
492+
493+
$this->assertContains('order[sort_by]', $parameterNames, 'Parameter order[sort_by] should be present');
494+
$this->assertNotContains('order[order[sort_by]]', $parameterNames, 'Parameter name should not be double-wrapped as order[order[sort_by]]');
495+
}
473496
}

0 commit comments

Comments
 (0)