Skip to content

Commit a4cd12b

Browse files
authored
fix: uri template should respect rfc 6570 (#5080)
1 parent 7044c5a commit a4cd12b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+136
-127
lines changed

src/Metadata/Resource/Factory/UriTemplateResourceMetadataCollectionFactory.php

+6-2
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ private function generateUriTemplate(HttpOperation $operation): string
105105
}
106106
}
107107

108-
return sprintf('%s.{_format}', $uriTemplate);
108+
return sprintf('%s{._format}', $uriTemplate);
109109
}
110110

111111
private function configureUriVariables(ApiResource|HttpOperation $operation): ApiResource|HttpOperation
@@ -144,8 +144,12 @@ private function configureUriVariables(ApiResource|HttpOperation $operation): Ap
144144
}
145145
$operation = $operation->withUriVariables($uriVariables);
146146

147+
if (str_ends_with($uriTemplate, '{._format}')) {
148+
$uriTemplate = substr($uriTemplate, 0, -10);
149+
}
150+
147151
$route = (new Route($uriTemplate))->compile();
148-
$variables = array_filter($route->getPathVariables(), fn ($v): bool => '_format' !== $v);
152+
$variables = $route->getPathVariables();
149153

150154
if (\count($variables) !== \count($uriVariables)) {
151155
$newUriVariables = [];

src/OpenApi/Factory/OpenApiFactory.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,8 @@ private function flattenMimeTypes(array $responseFormats): array
333333
*/
334334
private function getPath(string $path): string
335335
{
336-
if (str_ends_with($path, '.{_format}')) {
336+
// Handle either API Platform's URI Template (rfc6570) or Symfony's route
337+
if (str_ends_with($path, '{._format}') || str_ends_with($path, '.{_format}')) {
337338
$path = substr($path, 0, -10);
338339
}
339340

src/OpenApi/Serializer/NormalizeOperationNameTrait.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ trait NormalizeOperationNameTrait
2222
{
2323
private function normalizeOperationName(string $operationName): string
2424
{
25-
// .{_format} is related to the symfony router
26-
return preg_replace('/^_/', '', str_replace(['/', '.{_format}', '{', '}'], ['', '', '_', ''], $operationName));
25+
return preg_replace('/^_/', '', str_replace(['/', '{._format}', '{', '}'], ['', '', '_', ''], $operationName));
2726
}
2827
}

src/Symfony/Routing/ApiLoader.php

+5
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ public function load(mixed $data, string $type = null): RouteCollection
7575
$path = str_replace(sprintf('{%s}', $parameterName), $expandedValue, $path);
7676
}
7777

78+
// Within Symfony .{_format} is a special parameter but the rfc6570 specifies label expansion with a dot operator
79+
if (str_ends_with($path, '{._format}')) {
80+
$path = str_replace('{._format}', '.{_format}', $path);
81+
}
82+
7883
if (($controller = $operation->getController()) && !$this->container->has($controller)) {
7984
throw new RuntimeException(sprintf('There is no builtin action for the "%s" operation. You need to define the controller yourself.', $operationName));
8085
}

tests/Fixtures/TestBundle/Document/AbsoluteUrlDummy.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
2121

2222
#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::ABS_URL)]
23-
#[ApiResource(uriTemplate: '/absolute_url_relation_dummies/{id}/absolute_url_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: AbsoluteUrlRelationDummy::class, identifiers: ['id'], toProperty: 'absoluteUrlRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::ABS_URL, operations: [new GetCollection()])]
23+
#[ApiResource(uriTemplate: '/absolute_url_relation_dummies/{id}/absolute_url_dummies{._format}', uriVariables: ['id' => new Link(fromClass: AbsoluteUrlRelationDummy::class, identifiers: ['id'], toProperty: 'absoluteUrlRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::ABS_URL, operations: [new GetCollection()])]
2424
#[ODM\Document]
2525
class AbsoluteUrlDummy
2626
{

tests/Fixtures/TestBundle/Document/Answer.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
* Answer.
3030
*/
3131
#[ApiResource(operations: [new Get(), new Put(), new Patch(), new Delete(), new GetCollection(normalizationContext: ['groups' => ['foobar']])])]
32-
#[ApiResource(uriTemplate: '/answers/{id}/related_questions/{relatedQuestions}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], toProperty: 'answer'), 'relatedQuestions' => new Link(fromClass: Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])]
33-
#[ApiResource(uriTemplate: '/questions/{id}/answer.{_format}', uriVariables: ['id' => new Link(fromClass: Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])]
32+
#[ApiResource(uriTemplate: '/answers/{id}/related_questions/{relatedQuestions}/answer{._format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'], toProperty: 'answer'), 'relatedQuestions' => new Link(fromClass: Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])]
33+
#[ApiResource(uriTemplate: '/questions/{id}/answer{._format}', uriVariables: ['id' => new Link(fromClass: Question::class, identifiers: ['id'], fromProperty: 'answer')], status: 200, operations: [new Get()])]
3434
#[ODM\Document]
3535
class Answer
3636
{

tests/Fixtures/TestBundle/Document/Book.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*
2323
* @author Antoine Bluchet <[email protected]>
2424
*/
25-
#[ApiResource(operations: [new Get(), new Get(uriTemplate: '/books/by_isbn/{isbn}.{_format}', requirements: ['isbn' => '.+'], uriVariables: 'isbn')])]
25+
#[ApiResource(operations: [new Get(), new Get(uriTemplate: '/books/by_isbn/{isbn}{._format}', requirements: ['isbn' => '.+'], uriVariables: 'isbn')])]
2626
#[ODM\Document]
2727
class Book
2828
{

tests/Fixtures/TestBundle/Document/Dummy.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
* @author Alexandre Delplace <[email protected]>
3030
*/
3131
#[ApiResource(extraProperties: ['doctrine_mongodb' => ['execute_options' => ['allowDiskUse' => true]]], filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'])]
32-
#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])]
33-
#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy.{_format}', uriVariables: ['id' => new Link(fromClass: RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])]
32+
#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy{._format}', uriVariables: ['id' => new Link(fromClass: RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])]
33+
#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy{._format}', uriVariables: ['id' => new Link(fromClass: RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy')], status: 200, filters: ['my_dummy.mongodb.boolean', 'my_dummy.mongodb.date', 'my_dummy.mongodb.exists', 'my_dummy.mongodb.numeric', 'my_dummy.mongodb.order', 'my_dummy.mongodb.range', 'my_dummy.mongodb.search', 'my_dummy.property'], operations: [new Get()])]
3434
#[ODM\Document]
3535
class Dummy
3636
{

tests/Fixtures/TestBundle/Document/DummyAggregateOffer.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
* @author Antoine Bluchet <[email protected]>
2929
*/
3030
#[ApiResource]
31-
#[ApiResource(uriTemplate: '/dummy_products/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])]
32-
#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])]
31+
#[ApiResource(uriTemplate: '/dummy_products/{id}/offers{._format}', uriVariables: ['id' => new Link(fromClass: DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])]
32+
#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers{._format}', uriVariables: ['id' => new Link(fromClass: DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: DummyProduct::class, identifiers: ['id'], toProperty: 'product')], status: 200, operations: [new GetCollection()])]
3333
#[ODM\Document]
3434
class DummyAggregateOffer
3535
{

tests/Fixtures/TestBundle/Document/DummyOffer.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
* @author Antoine Bluchet <[email protected]>
2727
*/
2828
#[ApiResource]
29-
#[ApiResource(uriTemplate: '/dummy_aggregate_offers/{id}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])]
30-
#[ApiResource(uriTemplate: '/dummy_products/{id}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])]
31-
#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers/{offers}/offers.{_format}', uriVariables: ['id' => new Link(fromClass: DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])]
29+
#[ApiResource(uriTemplate: '/dummy_aggregate_offers/{id}/offers{._format}', uriVariables: ['id' => new Link(fromClass: DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])]
30+
#[ApiResource(uriTemplate: '/dummy_products/{id}/offers/{offers}/offers{._format}', uriVariables: ['id' => new Link(fromClass: DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])]
31+
#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products/{relatedProducts}/offers/{offers}/offers{._format}', uriVariables: ['id' => new Link(fromClass: DummyProduct::class, identifiers: ['id']), 'relatedProducts' => new Link(fromClass: DummyProduct::class, identifiers: ['id'], toProperty: 'product'), 'offers' => new Link(fromClass: DummyAggregateOffer::class, identifiers: ['id'], toProperty: 'aggregate')], status: 200, operations: [new GetCollection()])]
3232
#[ODM\Document]
3333
class DummyOffer
3434
{

tests/Fixtures/TestBundle/Document/DummyProduct.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
* @author Antoine Bluchet <[email protected]>
2929
*/
3030
#[ApiResource]
31-
#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products.{_format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, operations: [new GetCollection()])]
31+
#[ApiResource(uriTemplate: '/dummy_products/{id}/related_products{._format}', uriVariables: ['id' => new Link(fromClass: self::class, identifiers: ['id'])], status: 200, operations: [new GetCollection()])]
3232
#[ODM\Document]
3333
class DummyProduct
3434
{

tests/Fixtures/TestBundle/Document/DummyValidation.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
#[ApiResource(operations: [
2323
new GetCollection(),
24-
new Post(uriTemplate: 'dummy_validation.{_format}'),
24+
new Post(uriTemplate: 'dummy_validation{._format}'),
2525
new Post(routeName: 'post_validation_groups', validationContext: ['groups' => ['a']]),
2626
new Post(routeName: 'post_validation_sequence', validationContext: ['groups' => 'app.dummy_validation.group_generator']),
2727
]

tests/Fixtures/TestBundle/Document/FourthLevel.php

+6-6
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626
* @author Alan Poulain <[email protected]>
2727
*/
2828
#[ApiResource]
29-
#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
30-
#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
31-
#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
32-
#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
33-
#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
34-
#[ApiResource(uriTemplate: '/third_levels/{id}/fourth_level.{_format}', uriVariables: ['id' => new Link(fromClass: ThirdLevel::class, identifiers: ['id'], fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
29+
#[ApiResource(uriTemplate: '/dummies/{id}/related_dummies/{relatedDummies}/third_level/fourth_level{._format}', uriVariables: ['id' => new Link(fromClass: Dummy::class, identifiers: ['id'], fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
30+
#[ApiResource(uriTemplate: '/related_dummies/{id}/id/third_level/fourth_level{._format}', uriVariables: ['id' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
31+
#[ApiResource(uriTemplate: '/related_dummies/{id}/third_level/fourth_level{._format}', uriVariables: ['id' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
32+
#[ApiResource(uriTemplate: '/related_owned_dummies/{id}/owning_dummy/related_dummies/{relatedDummies}/third_level/fourth_level{._format}', uriVariables: ['id' => new Link(fromClass: RelatedOwnedDummy::class, identifiers: ['id'], fromProperty: 'owningDummy'), 'owningDummy' => new Link(fromClass: Dummy::class, identifiers: [], expandedValue: 'owning_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
33+
#[ApiResource(uriTemplate: '/related_owning_dummies/{id}/owned_dummy/related_dummies/{relatedDummies}/third_level/fourth_level{._format}', uriVariables: ['id' => new Link(fromClass: RelatedOwningDummy::class, identifiers: ['id'], fromProperty: 'ownedDummy'), 'ownedDummy' => new Link(fromClass: Dummy::class, identifiers: [], expandedValue: 'owned_dummy', fromProperty: 'relatedDummies'), 'relatedDummies' => new Link(fromClass: RelatedDummy::class, identifiers: ['id'], fromProperty: 'thirdLevel'), 'thirdLevel' => new Link(fromClass: ThirdLevel::class, identifiers: [], expandedValue: 'third_level', fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
34+
#[ApiResource(uriTemplate: '/third_levels/{id}/fourth_level{._format}', uriVariables: ['id' => new Link(fromClass: ThirdLevel::class, identifiers: ['id'], fromProperty: 'fourthLevel')], status: 200, operations: [new Get()])]
3535
#[ODM\Document]
3636
class FourthLevel
3737
{

tests/Fixtures/TestBundle/Document/Greeting.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
2020

2121
#[ApiResource]
22-
#[ApiResource(uriTemplate: '/people/{id}/sent_greetings.{_format}', uriVariables: ['id' => new Link(fromClass: Person::class, identifiers: ['id'], toProperty: 'sender')], status: 200, operations: [new GetCollection()])]
22+
#[ApiResource(uriTemplate: '/people/{id}/sent_greetings{._format}', uriVariables: ['id' => new Link(fromClass: Person::class, identifiers: ['id'], toProperty: 'sender')], status: 200, operations: [new GetCollection()])]
2323
#[ODM\Document]
2424
class Greeting
2525
{

tests/Fixtures/TestBundle/Document/NetworkPathDummy.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
2121

2222
#[ApiResource(urlGenerationStrategy: UrlGeneratorInterface::NET_PATH)]
23-
#[ApiResource(uriTemplate: '/network_path_relation_dummies/{id}/network_path_dummies.{_format}', uriVariables: ['id' => new Link(fromClass: NetworkPathRelationDummy::class, identifiers: ['id'], toProperty: 'networkPathRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::NET_PATH, operations: [new GetCollection()])]
23+
#[ApiResource(uriTemplate: '/network_path_relation_dummies/{id}/network_path_dummies{._format}', uriVariables: ['id' => new Link(fromClass: NetworkPathRelationDummy::class, identifiers: ['id'], toProperty: 'networkPathRelationDummy')], status: 200, urlGenerationStrategy: UrlGeneratorInterface::NET_PATH, operations: [new GetCollection()])]
2424
#[ODM\Document]
2525
class NetworkPathDummy
2626
{

0 commit comments

Comments
 (0)