Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
soyuka committed Jan 27, 2025
1 parent 97d25f5 commit c56b1af
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 94 deletions.
3 changes: 1 addition & 2 deletions src/JsonApi/JsonSchema/SchemaFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,7 @@ public function buildSchema(string $className, string $format = 'jsonapi', strin
}
// We don't use the serializer context here as JSON:API doesn't leverage serializer groups for related resources.
// That is done by query parameter. @see https://jsonapi.org/format/#fetching-includes
$operation ??= $this->findOperation($className, $type, $operation, $serializerContext, $format);
$serializerContext ??= $this->getSerializerContext($operation, $type);
$serializerContext ??= $this->getSerializerContext($operation ?? $this->findOperation($className, $type, $operation, $serializerContext, $format), $type);
$jsonApiSerializerContext = !($serializerContext[self::DISABLE_JSON_SCHEMA_SERIALIZER_GROUPS] ?? true) ? $serializerContext : [];
$schema = $this->schemaFactory->buildSchema($className, $format, $type, $operation, $schema, $jsonApiSerializerContext, $forceCollection);

Expand Down
29 changes: 17 additions & 12 deletions src/OpenApi/Factory/OpenApiFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
$errorOperations[$error] = $this->getErrorResource($error);
}

$openapiOperation = $this->addOperationErrors($openapiOperation, $errorOperations, $resourceMetadataCollection, $schema, $schemas);
$openapiOperation = $this->addOperationErrors($openapiOperation, $errorOperations, $resourceMetadataCollection, $schema, $schemas, $operation);
}

if ($overrideResponses || !$existingResponses) {
Expand All @@ -355,7 +355,7 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
$openapiOperation = $this->addOperationErrors($openapiOperation, [
ApiResourceError::class => $this->getErrorResource(ApiResourceError::class)->withStatus(400)->withDescription('Invalid input'),
ValidationException::class => $this->getErrorResource(ValidationException::class, 422, 'Unprocessable entity'), // we add defaults as ValidationException can not be installed
], $resourceMetadataCollection, $schema, $schemas);
], $resourceMetadataCollection, $schema, $schemas, $operation);
break;
case 'PATCH':
case 'PUT':
Expand All @@ -364,7 +364,7 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
$openapiOperation = $this->addOperationErrors($openapiOperation, [
ApiResourceError::class => $this->getErrorResource(ApiResourceError::class)->withStatus(400)->withDescription('Invalid input'),
ValidationException::class => $this->getErrorResource(ValidationException::class, 422, 'Unprocessable entity'), // we add defaults as ValidationException can not be installed
], $resourceMetadataCollection, $schema, $schemas);
], $resourceMetadataCollection, $schema, $schemas, $operation);
break;
case 'DELETE':
$successStatus = (string) $operation->getStatus() ?: 204;
Expand All @@ -376,13 +376,13 @@ private function collectPaths(ApiResource $resource, ResourceMetadataCollection
if ($overrideResponses && !isset($existingResponses[403]) && $operation->getSecurity()) {
$openapiOperation = $this->addOperationErrors($openapiOperation, [
ApiResourceError::class => $this->getErrorResource(ApiResourceError::class)->withStatus(403)->withDescription('Forbidden'),
], $resourceMetadataCollection, $schema, $schemas);
], $resourceMetadataCollection, $schema, $schemas, $operation);
}

if ($overrideResponses && !$operation instanceof CollectionOperationInterface && 'POST' !== $operation->getMethod() && !isset($existingResponses[404])) {
$openapiOperation = $this->addOperationErrors($openapiOperation, [
ApiResourceError::class => $this->getErrorResource(ApiResourceError::class)->withStatus(404)->withDescription('Not found'),
], $resourceMetadataCollection, $schema, $schemas);
], $resourceMetadataCollection, $schema, $schemas, $operation);
}

if (!$openapiOperation->getResponses()) {
Expand Down Expand Up @@ -576,7 +576,7 @@ private function getLinks(ResourceMetadataCollection $resourceMetadataCollection
}

if ($operationUriVariables[$parameterName]->getIdentifiers() === $uriVariableDefinition->getIdentifiers() && $operationUriVariables[$parameterName]->getFromClass() === $uriVariableDefinition->getFromClass()) {
$parameters[$parameterName] = '$request.path.'.$uriVariableDefinition->getIdentifiers()[0];
$parameters[$parameterName] = '$request.path.'.($uriVariableDefinition->getIdentifiers()[0] ?? 'id');
}
}

Expand All @@ -586,7 +586,7 @@ private function getLinks(ResourceMetadataCollection $resourceMetadataCollection
}

if ($uriVariableDefinition->getFromClass() === $currentOperation->getClass()) {
$parameters[$parameterName] = '$response.body#/'.$uriVariableDefinition->getIdentifiers()[0];
$parameters[$parameterName] = '$response.body#/'.($uriVariableDefinition->getIdentifiers()[0] ?? 'id');
}
}

Expand Down Expand Up @@ -857,16 +857,17 @@ private function addOperationErrors(
ResourceMetadataCollection $resourceMetadataCollection,
Schema $schema,
\ArrayObject $schemas,
HttpOperation $originalOperation,
): Operation {
$defaultFormat = ['json' => ['application/problem+json']];
foreach ($errors as $error => $errorResource) {
$responseMimeTypes = $this->flattenMimeTypes($errorResource->getOutputFormats() ?: []);

$responseMimeTypes = $this->flattenMimeTypes($errorResource->getOutputFormats() ?: $defaultFormat);
foreach ($errorResource->getOperations() as $errorOperation) {
if (false === $errorOperation->getOpenApi()) {
continue;
}

$responseMimeTypes += $this->flattenMimeTypes($errorOperation->getOutputFormats() ?: []);
$responseMimeTypes += $this->flattenMimeTypes($errorOperation->getOutputFormats() ?: $defaultFormat);
}

$operationErrorSchemas = [];
Expand All @@ -880,7 +881,7 @@ private function addOperationErrors(
throw new RuntimeException(\sprintf('The error class %s has no status defined, please either implement ProblemExceptionInterface, or make it an ErrorResource with a status', $error));
}

$operation = $this->buildOpenApiResponse($operation->getResponses() ?: [], $status, $errorResource->getDescription() ?? '', $operation, null, $responseMimeTypes, $operationErrorSchemas, $resourceMetadataCollection);
$operation = $this->buildOpenApiResponse($operation->getResponses() ?: [], $status, $errorResource->getDescription() ?? '', $operation, $originalOperation, $responseMimeTypes, $operationErrorSchemas, $resourceMetadataCollection);
}

return $operation;
Expand Down Expand Up @@ -909,7 +910,7 @@ private function getErrorResource(string $error, ?int $status = null, ?string $d

try {
$errorResource = $this->resourceMetadataFactory->create($error)[0] ?? new ErrorResource(status: $status, description: $description, class: ApiResourceError::class);
if (!is_a($errorResource, ErrorResource::class)) {
if (!($errorResource instanceof ErrorResource)) {
throw new RuntimeException(\sprintf('The error class %s is not an ErrorResource', $error));
}

Expand All @@ -925,6 +926,10 @@ private function getErrorResource(string $error, ?int $status = null, ?string $d
$errorResource = new ErrorResource(status: $status, description: $description, class: ApiResourceError::class);
}

if (!$errorResource->getClass()) {
$errorResource = $errorResource->withClass($error);
}

return $this->localErrorResourceCache[$error] = $errorResource;
}
}
Loading

0 comments on commit c56b1af

Please sign in to comment.