Skip to content

Commit

Permalink
feat(openapi): allow optional request body content
Browse files Browse the repository at this point in the history
  • Loading branch information
monitaurus committed May 18, 2024
1 parent e867d07 commit 8b57125
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 15 deletions.
22 changes: 15 additions & 7 deletions src/OpenApi/Factory/OpenApiFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -394,17 +394,25 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
);
$openapiOperation = $openapiOperation->withRequestBody(new RequestBody($contextRequestBody['description'] ?? '', new \ArrayObject($contextRequestBody['content']), $contextRequestBody['required'] ?? false));
} elseif (
null === $openapiOperation->getRequestBody() && \in_array($method, ['PATCH', 'PUT', 'POST'], true)
\in_array($method, ['PATCH', 'PUT', 'POST'], true)
&& !(false === ($input = $operation->getInput()) || (\is_array($input) && null === $input['class']))
) {
$operationInputSchemas = [];
foreach ($requestMimeTypes as $operationFormat) {
$operationInputSchema = $this->jsonSchemaFactory->buildSchema($resourceClass, $operationFormat, Schema::TYPE_INPUT, $operation, $schema, null, $forceSchemaCollection);
$operationInputSchemas[$operationFormat] = $operationInputSchema;
$this->appendSchemaDefinitions($schemas, $operationInputSchema->getDefinitions());
$content = $openapiOperation->getRequestBody()?->getContent();
if (null === $content) {
$operationInputSchemas = [];
foreach ($requestMimeTypes as $operationFormat) {
$operationInputSchema = $this->jsonSchemaFactory->buildSchema($resourceClass, $operationFormat, Schema::TYPE_INPUT, $operation, $schema, null, $forceSchemaCollection);
$operationInputSchemas[$operationFormat] = $operationInputSchema;
$this->appendSchemaDefinitions($schemas, $operationInputSchema->getDefinitions());
}
$content = $this->buildContent($requestMimeTypes, $operationInputSchemas);
}

$openapiOperation = $openapiOperation->withRequestBody(new RequestBody(sprintf('The %s %s resource', 'POST' === $method ? 'new' : 'updated', $resourceShortName), $this->buildContent($requestMimeTypes, $operationInputSchemas), true));
$openapiOperation = $openapiOperation->withRequestBody(new RequestBody(
description: $openapiOperation->getRequestBody()?->getDescription() ?? sprintf('The %s %s resource', 'POST' === $method ? 'new' : 'updated', $resourceShortName),
content: $content,
required: $openapiOperation->getRequestBody()?->getRequired() ?? true,
));
}

// TODO Remove in 4.0
Expand Down
6 changes: 3 additions & 3 deletions src/OpenApi/Model/RequestBody.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ final class RequestBody
{
use ExtensionTrait;

public function __construct(private string $description = '', private ?\ArrayObject $content = null, private bool $required = false)
public function __construct(private ?string $description = null, private ?\ArrayObject $content = null, private bool $required = false)
{
}

public function getDescription(): string
public function getDescription(): ?string
{
return $this->description;
}

public function getContent(): \ArrayObject
public function getContent(): ?\ArrayObject
{
return $this->content;
}
Expand Down
45 changes: 40 additions & 5 deletions src/OpenApi/Tests/Factory/OpenApiFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,11 @@ public function testInvoke(): void
'filteredDummyCollection' => (new GetCollection())->withUriTemplate('/filtered')->withFilters(['f1', 'f2', 'f3', 'f4', 'f5'])->withOperation($baseOperation),
// Paginated
'paginatedDummyCollection' => (new GetCollection())->withUriTemplate('/paginated')
->withPaginationClientEnabled(true)
->withPaginationClientItemsPerPage(true)
->withPaginationItemsPerPage(20)
->withPaginationMaximumItemsPerPage(80)
->withOperation($baseOperation),
->withPaginationClientEnabled(true)
->withPaginationClientItemsPerPage(true)
->withPaginationItemsPerPage(20)
->withPaginationMaximumItemsPerPage(80)
->withOperation($baseOperation),
'postDummyCollectionWithRequestBody' => (new Post())->withUriTemplate('/dummiesRequestBody')->withOperation($baseOperation)->withOpenapi(new OpenApiOperation(
requestBody: new RequestBody(
description: 'List of Ids',
Expand All @@ -202,6 +202,11 @@ public function testInvoke(): void
]),
),
)),
'postDummyCollectionWithRequestBodyWithoutContent' => (new Post())->withUriTemplate('/dummiesRequestBodyWithoutContent')->withOperation($baseOperation)->withOpenapi(new OpenApiOperation(
requestBody: new RequestBody(
description: 'Extended description for the new Dummy resource',
),
)),
'putDummyItemWithResponse' => (new Put())->withUriTemplate('/dummyitems/{id}')->withOperation($baseOperation)->withOpenapi(new OpenApiOperation(
responses: [
'200' => new OpenApiResponse(
Expand Down Expand Up @@ -872,6 +877,36 @@ public function testInvoke(): void
deprecated: false,
), $requestBodyPath->getPost());

$requestBodyPath = $paths->getPath('/dummiesRequestBodyWithoutContent');
$this->assertEquals(new Operation(
'postDummyCollectionWithRequestBodyWithoutContent',
['Dummy'],
[
'201' => new Response(
'Dummy resource created',
new \ArrayObject([
'application/ld+json' => new MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Dummy.OutputDto']))),
]),
null,
new \ArrayObject(['getDummyItem' => new Model\Link('getDummyItem', new \ArrayObject(['id' => '$response.body#/id']), null, 'This is a dummy')])
),
'400' => new Response('Invalid input'),
'422' => new Response('Unprocessable entity'),
],
'Creates a Dummy resource.',
'Creates a Dummy resource.',
null,
[],
new RequestBody(
'Extended description for the new Dummy resource',
new \ArrayObject([
'application/ld+json' => new MediaType(new \ArrayObject(new \ArrayObject(['$ref' => '#/components/schemas/Dummy']))),
]),
false
),
deprecated: false,
), $requestBodyPath->getPost());

$dummyItemPath = $paths->getPath('/dummyitems/{id}');
$this->assertEquals(new Operation(
'putDummyItemWithResponse',
Expand Down

0 comments on commit 8b57125

Please sign in to comment.