diff --git a/features/bootstrap/SwaggerContext.php b/features/bootstrap/SwaggerContext.php
index 61c333788c6..6e557c81302 100644
--- a/features/bootstrap/SwaggerContext.php
+++ b/features/bootstrap/SwaggerContext.php
@@ -176,9 +176,18 @@ private function getProperties(string $className, int $specVersion = 2): stdClas
private function getClassInfo(string $className, int $specVersion = 2): stdClass
{
$nodes = 2 === $specVersion ? $this->getLastJsonResponse()->{'definitions'} : $this->getLastJsonResponse()->{'components'}->{'schemas'};
- foreach ($nodes as $classTitle => $classData) {
- if ($classTitle === $className) {
- return $classData;
+
+ if (3 === $specVersion) {
+ foreach ($nodes as $classTitle => $classData) {
+ if (substr($classTitle, -strlen($className)) === $className) {
+ return $classData;
+ }
+ }
+ } else {
+ foreach ($nodes as $classTitle => $classData) {
+ if ($classTitle === $className) {
+ return $classData;
+ }
}
}
diff --git a/features/openapi/docs.feature b/features/openapi/docs.feature
index 0c8eb4dd50b..baac73155db 100644
--- a/features/openapi/docs.feature
+++ b/features/openapi/docs.feature
@@ -95,7 +95,7 @@ Feature: Documentation support
And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.parameters" should have 6 elements
# Subcollection - check schema
- And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.responses.200.content.application/ld+json.schema.items.$ref" should be equal to "#/components/schemas/RelatedToDummyFriend-fakemanytomany"
+ And the JSON node "paths./related_dummies/{id}/related_to_dummy_friends.get.responses.200.content.application/ld+json.schema.items.$ref" should be equal to "#/components/schemas/application-ld+json-RelatedToDummyFriend-fakemanytomany"
# Deprecations
And the JSON node "paths./dummies.get.deprecated" should not exist
diff --git a/src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php b/src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php
index 768cc4ab6fb..9d374a50d80 100644
--- a/src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php
+++ b/src/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtension.php
@@ -32,6 +32,7 @@
use ApiPlatform\Core\GraphQl\Resolver\QueryCollectionResolverInterface;
use ApiPlatform\Core\GraphQl\Resolver\QueryItemResolverInterface;
use ApiPlatform\Core\GraphQl\Type\Definition\TypeInterface as GraphQlTypeInterface;
+use ApiPlatform\Core\Swagger\SchemaFormatter\DefinititionNormalizerInterface;
use Doctrine\Common\Annotations\Annotation;
use phpDocumentor\Reflection\DocBlockFactoryInterface;
use Ramsey\Uuid\Uuid;
@@ -321,6 +322,9 @@ private function registerSwaggerConfiguration(ContainerBuilder $container, array
$container->setParameter('api_platform.enable_swagger', $config['enable_swagger']);
$container->setParameter('api_platform.swagger.api_keys', $config['swagger']['api_keys']);
+
+ $container->registerForAutoconfiguration(DefinititionNormalizerInterface::class)
+ ->addTag('api_platform.schema_formatter');
}
private function registerJsonApiConfiguration(array $formats, XmlFileLoader $loader): void
diff --git a/src/Bridge/Symfony/Bundle/Resources/config/swagger.xml b/src/Bridge/Symfony/Bundle/Resources/config/swagger.xml
index 9b2539356bc..90d8a8944ae 100644
--- a/src/Bridge/Symfony/Bundle/Resources/config/swagger.xml
+++ b/src/Bridge/Symfony/Bundle/Resources/config/swagger.xml
@@ -31,7 +31,10 @@
%api_platform.formats%
%api_platform.collection.pagination.client_enabled%
%api_platform.collection.pagination.enabled_parameter_name%
+
+
+
@@ -48,6 +51,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Exception/FormatterNotFoundException.php b/src/Exception/FormatterNotFoundException.php
new file mode 100644
index 00000000000..2a856637373
--- /dev/null
+++ b/src/Exception/FormatterNotFoundException.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Exception;
+
+final class FormatterNotFoundException extends InvalidArgumentException
+{
+}
diff --git a/src/Swagger/SchemaFormatter/ChainSchemaFormatter.php b/src/Swagger/SchemaFormatter/ChainSchemaFormatter.php
new file mode 100644
index 00000000000..d3d9d8eb877
--- /dev/null
+++ b/src/Swagger/SchemaFormatter/ChainSchemaFormatter.php
@@ -0,0 +1,44 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Swagger\SchemaFormatter;
+
+use ApiPlatform\Core\Exception\FormatterNotFoundException;
+
+final class ChainSchemaFormatter implements SchemaFormatterInterface
+{
+ private $formatters;
+
+ /**
+ * SchemaFormatterProvider constructor.
+ *
+ * @param DefinititionNormalizerInterface[] $formatters
+ */
+ public function __construct(/* iterable */ $formatters)
+ {
+ $this->formatters = $formatters;
+ }
+
+ public function getFormatter(string $mimeType): DefinititionNormalizerInterface
+ {
+ foreach ($this->formatters as $formatter) {
+ if ($formatter->supports($mimeType)) {
+ return $formatter;
+ }
+ }
+
+ throw new FormatterNotFoundException(
+ sprintf('No formatter supporting the "%s" MIME type is available.', $mimeType)
+ );
+ }
+}
diff --git a/src/Swagger/SchemaFormatter/DefaultDefinitionNormalizer.php b/src/Swagger/SchemaFormatter/DefaultDefinitionNormalizer.php
new file mode 100644
index 00000000000..b4cdee516a8
--- /dev/null
+++ b/src/Swagger/SchemaFormatter/DefaultDefinitionNormalizer.php
@@ -0,0 +1,34 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Swagger\SchemaFormatter;
+
+use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
+
+class DefaultDefinitionNormalizer implements DefinititionNormalizerInterface
+{
+ public function supports(string $mimeType): bool
+ {
+ return true;
+ }
+
+ public function buildBaseSchemaFormat(): array
+ {
+ return [];
+ }
+
+ public function setProperty(\ArrayObject $definitionSchema, $normalizedPropertyName, \ArrayObject $property, PropertyMetadata $propertyMetadata): void
+ {
+ $definitionSchema['properties'][$normalizedPropertyName] = $property;
+ }
+}
diff --git a/src/Swagger/SchemaFormatter/DefinititionNormalizerInterface.php b/src/Swagger/SchemaFormatter/DefinititionNormalizerInterface.php
new file mode 100644
index 00000000000..c668ecc5e52
--- /dev/null
+++ b/src/Swagger/SchemaFormatter/DefinititionNormalizerInterface.php
@@ -0,0 +1,34 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Swagger\SchemaFormatter;
+
+use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
+
+interface DefinititionNormalizerInterface
+{
+ /**
+ * Returns if the mimetype is supported by this formatter.
+ */
+ public function supports(string $mimeType): bool;
+
+ /**
+ * Builds the basic schema if needed for this mimetype.
+ */
+ public function buildBaseSchemaFormat(): array;
+
+ /**
+ * Sets the property in the correct fields for this mime type.
+ */
+ public function setProperty(\ArrayObject $definitionSchema, $normalizedPropertyName, \ArrayObject $property, PropertyMetadata $propertyMetadata): void;
+}
diff --git a/src/Swagger/SchemaFormatter/HydraDefinitionNormalizer.php b/src/Swagger/SchemaFormatter/HydraDefinitionNormalizer.php
new file mode 100644
index 00000000000..e25be7d7cdb
--- /dev/null
+++ b/src/Swagger/SchemaFormatter/HydraDefinitionNormalizer.php
@@ -0,0 +1,65 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Swagger\SchemaFormatter;
+
+use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
+
+final class HydraDefinitionNormalizer implements DefinititionNormalizerInterface
+{
+ public function supports(string $mimeType): bool
+ {
+ return 'application/ld+json' === $mimeType;
+ }
+
+ public function buildBaseSchemaFormat(): array
+ {
+ return [
+ 'hydra:member' => [
+ 'type' => 'object',
+ 'properties' => [
+ '@type' => [
+ 'type' => 'string',
+ ],
+ '@id' => [
+ 'type' => 'integer',
+ ],
+ ],
+ ],
+ ];
+ }
+
+ public function setProperty(\ArrayObject $definitionSchema, $normalizedPropertyName, \ArrayObject $property, PropertyMetadata $propertyMetadata): void
+ {
+ if (null !== $propertyMetadata->getType()
+ && 'object' === $propertyMetadata->getType()->getBuiltinType()
+ && isset($property['$ref'])
+ ) {
+ // @todo: Fix one to many statement.
+// if (false) {
+// $data = [
+// 'type' => 'object',
+// 'properties' => [
+// $data,
+// ],
+// ];
+// }
+
+ $definitionSchema['properties']['hydra:member']['properties'][$normalizedPropertyName] = $property;
+
+ return;
+ }
+
+ $definitionSchema['properties']['hydra:member']['properties'][$normalizedPropertyName] = $property;
+ }
+}
diff --git a/src/Swagger/SchemaFormatter/JsonApiDefinitionNormalizer.php b/src/Swagger/SchemaFormatter/JsonApiDefinitionNormalizer.php
new file mode 100644
index 00000000000..634ccf064d9
--- /dev/null
+++ b/src/Swagger/SchemaFormatter/JsonApiDefinitionNormalizer.php
@@ -0,0 +1,106 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Swagger\SchemaFormatter;
+
+use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
+
+final class JsonApiDefinitionNormalizer implements DefinititionNormalizerInterface
+{
+ public function supports(string $mimeType): bool
+ {
+ return 'application/vnd.api+json' === $mimeType;
+ }
+
+ public function buildBaseSchemaFormat(): array
+ {
+ return [
+ 'data' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'type' => [
+ 'type' => 'string',
+ ],
+ 'id' => [
+ 'type' => 'integer',
+ ],
+ 'attributes' => [
+ 'type' => 'object',
+ 'properties' => [],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ public function setProperty(\ArrayObject $definitionSchema, $normalizedPropertyName, \ArrayObject $property, PropertyMetadata $propertyMetadata): void
+ {
+ if ('id' === $normalizedPropertyName) {
+ $definitionSchema['properties']['data']['properties'][$normalizedPropertyName] = $property;
+ $normalizedPropertyName = '_id';
+ }
+
+ if (null !== $propertyMetadata->getType()
+ && 'object' === $propertyMetadata->getType()->getBuiltinType()
+ && isset($property['$ref'])
+ ) {
+ $data = [
+ 'type' => 'object',
+ 'properties' => [
+ 'type' => [
+ 'type' => 'string',
+ ],
+ 'id' => [
+ 'type' => 'string',
+ ],
+ ],
+ ];
+ // @todo: Fix one to many statement.
+// if (false) {
+// $data = [
+// 'type' => 'object',
+// 'properties' => [
+// $data,
+// ],
+// ];
+// }
+
+ $definitionSchema['properties']['data']['properties']['relationships'] = [
+ 'type' => 'object',
+ 'properties' => [
+ $normalizedPropertyName => [
+ 'type' => 'object',
+ 'properties' => [
+ 'links' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'self' => [
+ 'type' => 'string',
+ ],
+ 'related' => [
+ 'type' => 'string',
+ ],
+ ],
+ ],
+ 'data' => $data,
+ ],
+ ],
+ ],
+ ];
+
+ return;
+ }
+
+ $definitionSchema['properties']['data']['properties']['attributes']['properties'][$normalizedPropertyName] = $property;
+ }
+}
diff --git a/src/Swagger/SchemaFormatter/SchemaFormatterInterface.php b/src/Swagger/SchemaFormatter/SchemaFormatterInterface.php
new file mode 100644
index 00000000000..93bec80180c
--- /dev/null
+++ b/src/Swagger/SchemaFormatter/SchemaFormatterInterface.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Swagger\SchemaFormatter;
+
+interface SchemaFormatterInterface
+{
+}
diff --git a/src/Swagger/Serializer/DocumentationNormalizer.php b/src/Swagger/Serializer/DocumentationNormalizer.php
index 5105ab5f204..187c8c7b06c 100644
--- a/src/Swagger/Serializer/DocumentationNormalizer.php
+++ b/src/Swagger/Serializer/DocumentationNormalizer.php
@@ -30,6 +30,7 @@
use ApiPlatform\Core\Metadata\Resource\ResourceMetadata;
use ApiPlatform\Core\Operation\Factory\SubresourceOperationFactoryInterface;
use ApiPlatform\Core\PathResolver\OperationPathResolverInterface;
+use ApiPlatform\Core\Swagger\SchemaFormatter\SchemaFormatterInterface;
use Psr\Container\ContainerInterface;
use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
@@ -89,12 +90,13 @@ final class DocumentationNormalizer implements NormalizerInterface, CacheableSup
self::SPEC_VERSION => 2,
ApiGatewayNormalizer::API_GATEWAY => false,
];
+ private $schemaFormatter;
/**
* @param ContainerInterface|FilterCollection|null $filterLocator The new filter locator or the deprecated filter collection
* @param array|OperationAwareFormatsProviderInterface $formats
*/
- public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, OperationMethodResolverInterface $operationMethodResolver = null, OperationPathResolverInterface $operationPathResolver, UrlGeneratorInterface $urlGenerator = null, $filterLocator = null, NameConverterInterface $nameConverter = null, bool $oauthEnabled = false, string $oauthType = '', string $oauthFlow = '', string $oauthTokenUrl = '', string $oauthAuthorizationUrl = '', array $oauthScopes = [], array $apiKeys = [], SubresourceOperationFactoryInterface $subresourceOperationFactory = null, bool $paginationEnabled = true, string $paginationPageParameterName = 'page', bool $clientItemsPerPage = false, string $itemsPerPageParameterName = 'itemsPerPage', $formats = [], bool $paginationClientEnabled = false, string $paginationClientEnabledParameterName = 'pagination', array $defaultContext = [])
+ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, OperationMethodResolverInterface $operationMethodResolver = null, OperationPathResolverInterface $operationPathResolver, UrlGeneratorInterface $urlGenerator = null, $filterLocator = null, NameConverterInterface $nameConverter = null, bool $oauthEnabled = false, string $oauthType = '', string $oauthFlow = '', string $oauthTokenUrl = '', string $oauthAuthorizationUrl = '', array $oauthScopes = [], array $apiKeys = [], SubresourceOperationFactoryInterface $subresourceOperationFactory = null, bool $paginationEnabled = true, string $paginationPageParameterName = 'page', bool $clientItemsPerPage = false, string $itemsPerPageParameterName = 'itemsPerPage', $formats = [], bool $paginationClientEnabled = false, string $paginationClientEnabledParameterName = 'pagination', array $defaultContext = [], SchemaFormatterInterface $schemaFormatter = null)
{
if ($urlGenerator) {
@trigger_error(sprintf('Passing an instance of %s to %s() is deprecated since version 2.1 and will be removed in 3.0.', UrlGeneratorInterface::class, __METHOD__), E_USER_DEPRECATED);
@@ -136,6 +138,7 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa
$this->paginationClientEnabledParameterName = $paginationClientEnabledParameterName;
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);
+ $this->schemaFormatter = $schemaFormatter;
}
/**
@@ -260,9 +263,17 @@ private function updateGetOperation(bool $v3, \ArrayObject $pathOperation, array
$serializerContext = $this->getSerializerContext($operationType, false, $resourceMetadata, $operationName);
$responseDefinitionKey = false;
+ $responseDefinitionKeys = [];
$outputMetadata = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output', ['class' => $resourceClass], true);
if (null !== $outputClass = $outputMetadata['class'] ?? null) {
- $responseDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $outputClass, $serializerContext);
+ if ($v3) {
+ foreach ($mimeTypes as $mimeType) {
+ $responseDefinitionKeys[$mimeType] = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass,
+ $outputClass, $serializerContext, $mimeType, true);
+ }
+ } else {
+ $responseDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $outputClass, $serializerContext);
+ }
}
$successStatus = (string) $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'status', '200');
@@ -275,16 +286,21 @@ private function updateGetOperation(bool $v3, \ArrayObject $pathOperation, array
$pathOperation['summary'] ?? $pathOperation['summary'] = sprintf('Retrieves the collection of %s resources.', $resourceShortName);
$successResponse = ['description' => sprintf('%s collection response', $resourceShortName)];
-
- if ($responseDefinitionKey) {
- if ($v3) {
- $successResponse['content'] = array_fill_keys($mimeTypes, [
- 'schema' => [
- 'type' => 'array',
- 'items' => ['$ref' => sprintf('#/components/schemas/%s', $responseDefinitionKey)],
- ],
- ]);
- } else {
+ if ($v3) {
+ if (!empty($responseDefinitionKeys)) {
+ foreach ($mimeTypes as $mimeType) {
+ $successResponse['content'][$mimeType] = [
+ 'schema' => [
+ 'type' => 'array',
+ 'items' => [
+ '$ref' => sprintf('#/components/schemas/%s', $responseDefinitionKeys[$mimeType]),
+ ],
+ ],
+ ];
+ }
+ }
+ } else {
+ if ($responseDefinitionKey) {
$successResponse['schema'] = [
'type' => 'array',
'items' => ['$ref' => sprintf('#/definitions/%s', $responseDefinitionKey)],
@@ -305,10 +321,19 @@ private function updateGetOperation(bool $v3, \ArrayObject $pathOperation, array
$pathOperation = $this->addItemOperationParameters($v3, $pathOperation);
$successResponse = ['description' => sprintf('%s resource response', $resourceShortName)];
- if ($responseDefinitionKey) {
- if ($v3) {
- $successResponse['content'] = array_fill_keys($mimeTypes, ['schema' => ['$ref' => sprintf('#/components/schemas/%s', $responseDefinitionKey)]]);
- } else {
+
+ if ($v3) {
+ if (!empty($responseDefinitionKeys)) {
+ foreach ($mimeTypes as $mimeType) {
+ $successResponse['content'][$mimeType] = [
+ 'schema' => [
+ '$ref' => sprintf('#/components/schemas/%s', $responseDefinitionKeys[$mimeType]),
+ ],
+ ];
+ }
+ }
+ } else {
+ if ($responseDefinitionKey) {
$successResponse['schema'] = ['$ref' => sprintf('#/definitions/%s', $responseDefinitionKey)];
}
}
@@ -367,7 +392,7 @@ private function addSubresourceOperation(bool $v3, array $subresourceOperation,
$subResourceMetadata = $this->resourceMetadataFactory->create($subresourceOperation['resource_class']);
$serializerContext = $this->getSerializerContext(OperationType::SUBRESOURCE, false, $subResourceMetadata, $operationName);
- $responseDefinitionKey = $this->getDefinition($v3, $definitions, $subResourceMetadata, $subresourceOperation['resource_class'], null, $serializerContext);
+
$pathOperation = new \ArrayObject([]);
$pathOperation['tags'] = $subresourceOperation['shortNames'];
$pathOperation['operationId'] = $operationId;
@@ -390,7 +415,19 @@ private function addSubresourceOperation(bool $v3, array $subresourceOperation,
$pathOperation['produces'] = $mimeTypes;
}
- $pathOperation['responses'] = $this->getSubresourceResponse($v3, $mimeTypes, $subresourceOperation['collection'], $subresourceOperation['shortNames'][0], $responseDefinitionKey);
+ $responseDefinitionKeys = [];
+ $responseDefinitionKey = '';
+ if ($v3) {
+ foreach ($responseMimeTypes ?? $mimeTypes as $mimeType) {
+ $responseDefinitionKeys[$mimeType] = $this->getDefinition($v3, $definitions, $subResourceMetadata,
+ $subresourceOperation['resource_class'], null, $serializerContext, $mimeType);
+ }
+ } else {
+ $responseDefinitionKey = $this->getDefinition($v3, $definitions, $subResourceMetadata,
+ $subresourceOperation['resource_class'], null, $serializerContext);
+ }
+
+ $pathOperation['responses'] = $this->getSubresourceResponse($v3, $mimeTypes, $subresourceOperation['collection'], $subresourceOperation['shortNames'][0], $responseDefinitionKey, $responseDefinitionKeys);
// Avoid duplicates parameters when there is a filter on a subresource identifier
$parametersMemory = [];
$pathOperation['parameters'] = [];
@@ -417,7 +454,7 @@ private function addSubresourceOperation(bool $v3, array $subresourceOperation,
return new \ArrayObject(['get' => $pathOperation]);
}
- private function getSubresourceResponse(bool $v3, $mimeTypes, bool $collection, string $shortName, string $definitionKey): array
+ private function getSubresourceResponse(bool $v3, $mimeTypes, bool $collection, string $shortName, string $definitionKey, array $definitionKeys = []): array
{
if ($collection) {
$okResponse = [
@@ -425,7 +462,9 @@ private function getSubresourceResponse(bool $v3, $mimeTypes, bool $collection,
];
if ($v3) {
- $okResponse['content'] = array_fill_keys($mimeTypes, ['schema' => ['type' => 'array', 'items' => ['$ref' => sprintf('#/components/schemas/%s', $definitionKey)]]]);
+ foreach ($mimeTypes as $mimeType) {
+ $okResponse['content'][$mimeType] = ['schema' => ['type' => 'array', 'items' => ['$ref' => sprintf('#/components/schemas/%s', $definitionKeys[$mimeType])]]];
+ }
} else {
$okResponse['schema'] = ['type' => 'array', 'items' => ['$ref' => sprintf('#/definitions/%s', $definitionKey)]];
}
@@ -435,7 +474,16 @@ private function getSubresourceResponse(bool $v3, $mimeTypes, bool $collection,
];
if ($v3) {
- $okResponse['content'] = array_fill_keys($mimeTypes, ['schema' => ['$ref' => sprintf('#/components/schemas/%s', $definitionKey)]]);
+ foreach ($mimeTypes as $mimeType) {
+ $okResponse['content'][$mimeType] = [
+ 'schema' => [
+ '$ref' => sprintf(
+ '#/components/schemas/%s',
+ $definitionKeys[$mimeType]
+ ),
+ ],
+ ];
+ }
} else {
$okResponse['schema'] = ['$ref' => sprintf('#/definitions/%s', $definitionKey)];
}
@@ -459,19 +507,40 @@ private function updatePostOperation(bool $v3, \ArrayObject $pathOperation, arra
}
$responseDefinitionKey = false;
+ $responseDefinitionKeys = [];
$outputMetadata = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output', ['class' => $resourceClass], true);
if (null !== $outputClass = $outputMetadata['class'] ?? null) {
- $responseDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $outputClass, $this->getSerializerContext($operationType, false, $resourceMetadata, $operationName));
+ if ($v3) {
+ foreach ($responseMimeTypes as $mimeType) {
+ $responseDefinitionKeys[$mimeType] = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass,
+ $outputClass,
+ $this->getSerializerContext($operationType, false, $resourceMetadata, $operationName), $mimeType, true);
+ }
+ } else {
+ $responseDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass,
+ $outputClass,
+ $this->getSerializerContext($operationType, false, $resourceMetadata, $operationName));
+ }
}
$successResponse = ['description' => sprintf('%s resource created', $resourceShortName)];
- if ($responseDefinitionKey) {
- if ($v3) {
- $successResponse['content'] = array_fill_keys($responseMimeTypes, ['schema' => ['$ref' => sprintf('#/components/schemas/%s', $responseDefinitionKey)]]);
+
+ if ($v3) {
+ if (!empty($responseDefinitionKeys)) {
+ foreach ($responseMimeTypes as $mimeType) {
+ $successResponse['content'][$mimeType] = [
+ 'schema' => [
+ '$ref' => sprintf('#/components/schemas/%s',
+ $responseDefinitionKeys[$mimeType]),
+ ],
+ ];
+ }
if ($links[$key = 'get'.ucfirst($resourceShortName).ucfirst(OperationType::ITEM)] ?? null) {
$successResponse['links'] = [ucfirst($key) => $links[$key]];
}
- } else {
+ }
+ } else {
+ if ($responseDefinitionKey) {
$successResponse['schema'] = ['$ref' => sprintf('#/definitions/%s', $responseDefinitionKey)];
}
}
@@ -487,19 +556,24 @@ private function updatePostOperation(bool $v3, \ArrayObject $pathOperation, arra
return $pathOperation;
}
- $requestDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $inputClass, $this->getSerializerContext($operationType, true, $resourceMetadata, $operationName));
if ($v3) {
+ $content = [];
+ foreach ($responseMimeTypes as $mimeType) {
+ $requestDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $inputClass, $this->getSerializerContext($operationType, true, $resourceMetadata, $operationName), $mimeType, true);
+ $content[$mimeType] = ['schema' => ['$ref' => sprintf('#/components/schemas/%s', $requestDefinitionKey)]];
+ }
$pathOperation['requestBody'] ?? $pathOperation['requestBody'] = [
- 'content' => array_fill_keys($requestMimeTypes, ['schema' => ['$ref' => sprintf('#/components/schemas/%s', $requestDefinitionKey)]]),
+ 'content' => $content,
'description' => sprintf('The new %s resource', $resourceShortName),
];
} else {
- $userDefinedParameters ?? $pathOperation['parameters'][] = [
+ $requestDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $inputClass, $this->getSerializerContext($operationType, true, $resourceMetadata, $operationName));
+ $userDefinedParameters ?? $pathOperation['parameters'] = [[
'name' => lcfirst($resourceShortName),
'in' => 'body',
'description' => sprintf('The new %s resource', $resourceShortName),
'schema' => ['$ref' => sprintf('#/definitions/%s', $requestDefinitionKey)],
- ];
+ ]];
}
return $pathOperation;
@@ -517,16 +591,40 @@ private function updatePutOperation(bool $v3, \ArrayObject $pathOperation, array
$pathOperation = $this->addItemOperationParameters($v3, $pathOperation);
$responseDefinitionKey = false;
+ $responseDefinitionKeys = [];
$outputMetadata = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, 'output', ['class' => $resourceClass], true);
if (null !== $outputClass = $outputMetadata['class'] ?? null) {
- $responseDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $outputClass, $this->getSerializerContext($operationType, false, $resourceMetadata, $operationName));
+ if ($v3) {
+ foreach ($responseMimeTypes as $mimeType) {
+ $responseDefinitionKeys[$mimeType] = $this->getDefinition($v3, $definitions, $resourceMetadata,
+ $resourceClass,
+ $outputClass,
+ $this->getSerializerContext($operationType, false, $resourceMetadata, $operationName),
+ $mimeType,
+ true);
+ }
+ } else {
+ $responseDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass,
+ $outputClass,
+ $this->getSerializerContext($operationType, false, $resourceMetadata, $operationName));
+ }
}
$successResponse = ['description' => sprintf('%s resource updated', $resourceShortName)];
- if ($responseDefinitionKey) {
- if ($v3) {
- $successResponse['content'] = array_fill_keys($responseMimeTypes, ['schema' => ['$ref' => sprintf('#/components/schemas/%s', $responseDefinitionKey)]]);
- } else {
+
+ if ($v3) {
+ if (!empty($responseDefinitionKeys)) {
+ foreach ($responseMimeTypes as $mimeType) {
+ $successResponse['content'][$mimeType] = [
+ 'schema' => [
+ '$ref' => sprintf('#/components/schemas/%s',
+ $responseDefinitionKeys[$mimeType]),
+ ],
+ ];
+ }
+ }
+ } else {
+ if ($responseDefinitionKey) {
$successResponse['schema'] = ['$ref' => sprintf('#/definitions/%s', $responseDefinitionKey)];
}
}
@@ -542,13 +640,18 @@ private function updatePutOperation(bool $v3, \ArrayObject $pathOperation, array
return $pathOperation;
}
- $requestDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $inputClass, $this->getSerializerContext($operationType, true, $resourceMetadata, $operationName));
if ($v3) {
+ $content = [];
+ foreach ($responseMimeTypes as $mimeType) {
+ $requestDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $inputClass, $this->getSerializerContext($operationType, true, $resourceMetadata, $operationName), $mimeType, true);
+ $content[$mimeType] = ['schema' => ['$ref' => sprintf('#/components/schemas/%s', $requestDefinitionKey)]];
+ }
$pathOperation['requestBody'] ?? $pathOperation['requestBody'] = [
- 'content' => array_fill_keys($requestMimeTypes, ['schema' => ['$ref' => sprintf('#/components/schemas/%s', $requestDefinitionKey)]]),
+ 'content' => $content,
'description' => sprintf('The updated %s resource', $resourceShortName),
];
} else {
+ $requestDefinitionKey = $this->getDefinition($v3, $definitions, $resourceMetadata, $resourceClass, $inputClass, $this->getSerializerContext($operationType, true, $resourceMetadata, $operationName));
$pathOperation['parameters'][] = [
'name' => lcfirst($resourceShortName),
'in' => 'body',
@@ -584,7 +687,7 @@ private function addItemOperationParameters(bool $v3, \ArrayObject $pathOperatio
return $pathOperation;
}
- private function getDefinition(bool $v3, \ArrayObject $definitions, ResourceMetadata $resourceMetadata, string $resourceClass, ?string $publicClass, array $serializerContext = null): string
+ private function getDefinition(bool $v3, \ArrayObject $definitions, ResourceMetadata $resourceMetadata, string $resourceClass, ?string $publicClass, array $serializerContext = null, $mimeType = null, bool $urlencode = false): string
{
$keyPrefix = $resourceMetadata->getShortName();
if (null !== $publicClass && $resourceClass !== $publicClass) {
@@ -597,9 +700,23 @@ private function getDefinition(bool $v3, \ArrayObject $definitions, ResourceMeta
$definitionKey = $this->getDefinitionKey($keyPrefix, (array) ($serializerContext[AbstractNormalizer::GROUPS] ?? []));
}
- if (!isset($definitions[$definitionKey])) {
- $definitions[$definitionKey] = []; // Initialize first to prevent infinite loop
- $definitions[$definitionKey] = $this->getDefinitionSchema($v3, $publicClass ?? $resourceClass, $resourceMetadata, $definitions, $serializerContext);
+ if ($v3) {
+ $definitionKey = str_replace('/', '-', $mimeType).'-'.$definitionKey;
+ if (!isset($definitions[$definitionKey])) {
+ $definitions[$definitionKey] = [];
+ $definitions[$definitionKey] = $this->getDefinitionSchema($v3,
+ $publicClass ?? $resourceClass, $resourceMetadata, $definitions, $serializerContext, $mimeType);
+ }
+ } else {
+ if (!isset($definitions[$definitionKey])) {
+ $definitions[$definitionKey] = []; // Initialize first to prevent infinite loop
+ $definitions[$definitionKey] = $this->getDefinitionSchema($v3, $publicClass ?? $resourceClass,
+ $resourceMetadata, $definitions, $serializerContext);
+ }
+ }
+
+ if ($urlencode) {
+ return urlencode($definitionKey);
}
return $definitionKey;
@@ -614,8 +731,10 @@ private function getDefinitionKey(string $resourceShortName, array $groups): str
* Gets a definition Schema Object.
*
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject
+ *
+ * @param mixed|null $mimeType
*/
- private function getDefinitionSchema(bool $v3, string $resourceClass, ResourceMetadata $resourceMetadata, \ArrayObject $definitions, array $serializerContext = null): \ArrayObject
+ private function getDefinitionSchema(bool $v3, string $resourceClass, ResourceMetadata $resourceMetadata, \ArrayObject $definitions, array $serializerContext = null, $mimeType = null): \ArrayObject
{
$definitionSchema = new \ArrayObject(['type' => 'object']);
@@ -628,6 +747,14 @@ private function getDefinitionSchema(bool $v3, string $resourceClass, ResourceMe
}
$options = isset($serializerContext[AbstractNormalizer::GROUPS]) ? ['serializer_groups' => $serializerContext[AbstractNormalizer::GROUPS]] : [];
+
+ $schemaFormatter = null;
+ if ($v3) {
+ $schemaFormatter = $this->schemaFormatter->getFormatter($mimeType);
+
+ $definitionSchema['properties'] = $schemaFormatter->buildBaseSchemaFormat();
+ }
+
foreach ($this->propertyNameCollectionFactory->create($resourceClass, $options) as $propertyName) {
$propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName);
if (!$propertyMetadata->isReadable() && !$propertyMetadata->isWritable()) {
@@ -639,7 +766,11 @@ private function getDefinitionSchema(bool $v3, string $resourceClass, ResourceMe
$definitionSchema['required'][] = $normalizedPropertyName;
}
- $definitionSchema['properties'][$normalizedPropertyName] = $this->getPropertySchema($v3, $propertyMetadata, $definitions, $serializerContext);
+ if ($v3 && null !== $schemaFormatter) {
+ $schemaFormatter->setProperty($definitionSchema, $normalizedPropertyName, $this->getPropertySchema($v3, $propertyMetadata, $definitions, $serializerContext, $mimeType), $propertyMetadata);
+ } else {
+ $definitionSchema['properties'][$normalizedPropertyName] = $this->getPropertySchema($v3, $propertyMetadata, $definitions, $serializerContext);
+ }
}
return $definitionSchema;
@@ -650,7 +781,7 @@ private function getDefinitionSchema(bool $v3, string $resourceClass, ResourceMe
*
* @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject
*/
- private function getPropertySchema(bool $v3, PropertyMetadata $propertyMetadata, \ArrayObject $definitions, array $serializerContext = null): \ArrayObject
+ private function getPropertySchema(bool $v3, PropertyMetadata $propertyMetadata, \ArrayObject $definitions, array $serializerContext = null, string $mimeType = null): \ArrayObject
{
$propertySchema = new \ArrayObject($propertyMetadata->getAttributes()[$v3 ? 'openapi_context' : 'swagger_context'] ?? []);
@@ -675,7 +806,7 @@ private function getPropertySchema(bool $v3, PropertyMetadata $propertyMetadata,
$className = $valueType->getClassName();
}
- $valueSchema = $this->getType($v3, $builtinType, $isCollection, $className, $propertyMetadata->isReadableLink(), $definitions, $serializerContext);
+ $valueSchema = $this->getType($v3, $builtinType, $isCollection, $className, $propertyMetadata->isReadableLink(), $definitions, $serializerContext, $mimeType);
return new \ArrayObject((array) $propertySchema + $valueSchema);
}
@@ -683,10 +814,10 @@ private function getPropertySchema(bool $v3, PropertyMetadata $propertyMetadata,
/**
* Gets the Swagger's type corresponding to the given PHP's type.
*/
- private function getType(bool $v3, string $type, bool $isCollection, ?string $className, ?bool $readableLink, \ArrayObject $definitions, array $serializerContext = null): array
+ private function getType(bool $v3, string $type, bool $isCollection, ?string $className, ?bool $readableLink, \ArrayObject $definitions, array $serializerContext = null, string $mimeType = null): array
{
if ($isCollection) {
- return ['type' => 'array', 'items' => $this->getType($v3, $type, false, $className, $readableLink, $definitions, $serializerContext)];
+ return ['type' => 'array', 'items' => $this->getType($v3, $type, false, $className, $readableLink, $definitions, $serializerContext, $mimeType)];
}
if (Type::BUILTIN_TYPE_STRING === $type) {
@@ -719,9 +850,18 @@ private function getType(bool $v3, string $type, bool $isCollection, ?string $cl
}
if (true === $readableLink) {
+ if ($v3) {
+ return [
+ '$ref' => sprintf(
+ '#/components/schemas/%s',
+ $this->getDefinition($v3, $definitions, $resourceMetadata = $this->resourceMetadataFactory->create($className), $className, $resourceMetadata->getAttribute('output')['class'] ?? $className, $serializerContext, $mimeType, true)
+ ),
+ ];
+ }
+
return [
'$ref' => sprintf(
- $v3 ? '#/components/schemas/%s' : '#/definitions/%s',
+ '#/definitions/%s',
$this->getDefinition($v3, $definitions, $resourceMetadata = $this->resourceMetadataFactory->create($className), $className, $resourceMetadata->getAttribute('output')['class'] ?? $className, $serializerContext)
),
];
diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php
index e3b5c5b9af4..75cc68112d5 100644
--- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php
+++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php
@@ -73,6 +73,7 @@
use ApiPlatform\Core\Serializer\Filter\GroupFilter;
use ApiPlatform\Core\Serializer\Filter\PropertyFilter;
use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface;
+use ApiPlatform\Core\Swagger\SchemaFormatter\DefinititionNormalizerInterface;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\TestBundle;
use ApiPlatform\Core\Validator\ValidatorInterface;
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
@@ -1034,6 +1035,10 @@ private function getBaseContainerBuilderProphecy(array $doctrineIntegrationsToLo
->willReturn($this->childDefinitionProphecy)->shouldBeCalledTimes(1);
$this->childDefinitionProphecy->addTag('api_platform.data_transformer')->shouldBeCalledTimes(1);
+ $containerBuilderProphecy->registerForAutoconfiguration(DefinititionNormalizerInterface::class)
+ ->willReturn($this->childDefinitionProphecy)->shouldBeCalledTimes(1);
+ $this->childDefinitionProphecy->addTag('api_platform.schema_formatter')->shouldBeCalledTimes(1);
+
$containerBuilderProphecy->addResource(Argument::type(DirectoryResource::class))->shouldBeCalled();
$parameters = [
@@ -1162,6 +1167,9 @@ private function getBaseContainerBuilderProphecy(array $doctrineIntegrationsToLo
'api_platform.swagger.normalizer.documentation',
'api_platform.validator',
'test.api_platform.client',
+ 'api_platform.schema_formatter.json',
+ 'api_platform.schema_formatter.api+json',
+ 'api_platform.schema_formatter.provider',
];
if (\in_array('odm', $doctrineIntegrationsToLoad, true)) {
diff --git a/tests/Swagger/SchemaFormatter/ChainSchemaFormatterTest.php b/tests/Swagger/SchemaFormatter/ChainSchemaFormatterTest.php
new file mode 100644
index 00000000000..d3e4d478a92
--- /dev/null
+++ b/tests/Swagger/SchemaFormatter/ChainSchemaFormatterTest.php
@@ -0,0 +1,55 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Tests\Swagger\SchemaFormatter;
+
+use ApiPlatform\Core\Exception\FormatterNotFoundException;
+use ApiPlatform\Core\Swagger\SchemaFormatter\ChainSchemaFormatter;
+use ApiPlatform\Core\Swagger\SchemaFormatter\DefaultDefinitionNormalizer;
+use ApiPlatform\Core\Swagger\SchemaFormatter\HydraDefinitionNormalizer;
+use ApiPlatform\Core\Swagger\SchemaFormatter\JsonApiDefinitionNormalizer;
+use PHPUnit\Framework\TestCase;
+
+class ChainSchemaFormatterTest extends TestCase
+{
+ public function testGetFormatter()
+ {
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ new HydraDefinitionNormalizer(),
+ new JsonApiDefinitionNormalizer(),
+ new DefaultDefinitionNormalizer(),
+ ]);
+ $formatter = $schemaFormatterFactory->getFormatter('application/json');
+ $this->assertInstanceOf(DefaultDefinitionNormalizer::class, $formatter);
+ }
+
+ public function testGetFormatterDefault()
+ {
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ new HydraDefinitionNormalizer(),
+ new JsonApiDefinitionNormalizer(),
+ new DefaultDefinitionNormalizer(),
+ ]);
+
+ $formatter = $schemaFormatterFactory->getFormatter('application/json-test');
+ $this->assertInstanceOf(DefaultDefinitionNormalizer::class, $formatter);
+ }
+
+ public function testGetFormatterExceptionNoFormatters()
+ {
+ $schemaFormatterFactory = new ChainSchemaFormatter([]);
+
+ $this->expectException(FormatterNotFoundException::class);
+ $schemaFormatterFactory->getFormatter('application/json-test');
+ }
+}
diff --git a/tests/Swagger/SchemaFormatter/DefaultSchemaFormatterTest.php b/tests/Swagger/SchemaFormatter/DefaultSchemaFormatterTest.php
new file mode 100644
index 00000000000..2ce27b439d9
--- /dev/null
+++ b/tests/Swagger/SchemaFormatter/DefaultSchemaFormatterTest.php
@@ -0,0 +1,64 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Tests\Swagger\SchemaFormatter;
+
+use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
+use ApiPlatform\Core\Swagger\SchemaFormatter\DefaultDefinitionNormalizer;
+use PHPUnit\Framework\TestCase;
+
+class DefaultSchemaFormatterTest extends TestCase
+{
+ public function testSupports()
+ {
+ $schemaFormatter = new DefaultDefinitionNormalizer();
+ $this->assertTrue($schemaFormatter->supports('application/json'));
+ }
+
+ public function testSupportsNotSupported()
+ {
+ $schemaFormatter = new DefaultDefinitionNormalizer();
+ $this->assertTrue($schemaFormatter->supports('application/jso'));
+ }
+
+ public function testBuildBaseSchemaFormat()
+ {
+ $schemaFormatter = new DefaultDefinitionNormalizer();
+ $this->assertEquals([], $schemaFormatter->buildBaseSchemaFormat());
+ }
+
+ public function testSetProperty()
+ {
+ $schemaFormatter = new DefaultDefinitionNormalizer();
+ $definitionSchema = new \ArrayObject([]);
+ $normalizedPropertyName = 'test';
+ $property = new \ArrayObject([
+ 'test' => 'foo',
+ ]);
+ $propertyMetadata = new PropertyMetadata();
+
+ $definitionSchema['properties'] = $schemaFormatter->buildBaseSchemaFormat();
+ $schemaFormatter->setProperty($definitionSchema, $normalizedPropertyName, $property, $propertyMetadata);
+
+ $this->assertEquals(
+ new \ArrayObject([
+ 'properties' => [
+ 'test' => new \ArrayObject([
+ 'test' => 'foo',
+ ]),
+ ],
+ ]),
+ $definitionSchema
+ );
+ }
+}
diff --git a/tests/Swagger/SchemaFormatter/JsonApiSchemaFormatterTest.php b/tests/Swagger/SchemaFormatter/JsonApiSchemaFormatterTest.php
new file mode 100644
index 00000000000..80294ba9ca8
--- /dev/null
+++ b/tests/Swagger/SchemaFormatter/JsonApiSchemaFormatterTest.php
@@ -0,0 +1,99 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace ApiPlatform\Core\Tests\Swagger\SchemaFormatter;
+
+use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
+use ApiPlatform\Core\Swagger\SchemaFormatter\JsonApiDefinitionNormalizer;
+use PHPUnit\Framework\TestCase;
+
+class JsonApiSchemaFormatterTest extends TestCase
+{
+ public function testSupports()
+ {
+ $schemaFormatter = new JsonApiDefinitionNormalizer();
+ $this->assertTrue($schemaFormatter->supports('application/vnd.api+json'));
+ }
+
+ public function testSupportsNotSupported()
+ {
+ $schemaFormatter = new JsonApiDefinitionNormalizer();
+ $this->assertFalse($schemaFormatter->supports('application/jso'));
+ }
+
+ public function testBuildBaseSchemaFormat()
+ {
+ $schemaFormatter = new JsonApiDefinitionNormalizer();
+ $this->assertEquals(
+ [
+ 'data' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'type' => [
+ 'type' => 'string',
+ ],
+ 'id' => [
+ 'type' => 'integer',
+ ],
+ 'attributes' => [
+ 'type' => 'object',
+ 'properties' => [],
+ ],
+ ],
+ ],
+ ],
+ $schemaFormatter->buildBaseSchemaFormat()
+ );
+ }
+
+ public function testSetProperty()
+ {
+ $schemaFormatter = new JsonApiDefinitionNormalizer();
+ $definitionSchema = new \ArrayObject([]);
+ $normalizedPropertyName = 'test';
+ $property = new \ArrayObject([
+ 'test' => 'foo',
+ ]);
+ $propertyMetadata = new PropertyMetadata();
+
+ $definitionSchema['properties'] = $schemaFormatter->buildBaseSchemaFormat();
+ $schemaFormatter->setProperty($definitionSchema, $normalizedPropertyName, $property, $propertyMetadata);
+
+ $this->assertEquals(
+ new \ArrayObject([
+ 'properties' => [
+ 'data' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'type' => [
+ 'type' => 'string',
+ ],
+ 'id' => [
+ 'type' => 'integer',
+ ],
+ 'attributes' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'test' => new \ArrayObject([
+ 'test' => 'foo',
+ ]),
+ ],
+ ],
+ ],
+ ],
+ ],
+ ]),
+ $definitionSchema
+ );
+ }
+}
diff --git a/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php b/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php
index d7ab92d2d52..14aec48e834 100644
--- a/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php
+++ b/tests/Swagger/Serializer/DocumentationNormalizerV3Test.php
@@ -34,6 +34,10 @@
use ApiPlatform\Core\PathResolver\CustomOperationPathResolver;
use ApiPlatform\Core\PathResolver\OperationPathResolver;
use ApiPlatform\Core\PathResolver\OperationPathResolverInterface;
+use ApiPlatform\Core\Swagger\SchemaFormatter\ChainSchemaFormatter;
+use ApiPlatform\Core\Swagger\SchemaFormatter\DefaultDefinitionNormalizer;
+use ApiPlatform\Core\Swagger\SchemaFormatter\HydraDefinitionNormalizer;
+use ApiPlatform\Core\Swagger\SchemaFormatter\JsonApiDefinitionNormalizer;
use ApiPlatform\Core\Swagger\Serializer\DocumentationNormalizer;
use ApiPlatform\Core\Tests\Fixtures\DummyFilter;
use ApiPlatform\Core\Tests\Fixtures\TestBundle\Entity\Answer;
@@ -115,6 +119,9 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
$resourceClassResolverProphecy->isResourceClass(Dummy::class)->willReturn(true);
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
@@ -141,7 +148,8 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -184,7 +192,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
'application/ld+json' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -197,7 +205,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
'description' => 'The new Dummy resource',
@@ -208,7 +216,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
'description' => 'Dummy resource created',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
'links' => [
@@ -242,7 +250,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
'description' => 'Dummy resource response',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -255,7 +263,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
'description' => 'The updated Dummy resource',
@@ -274,7 +282,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
'description' => 'Dummy resource updated',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -311,7 +319,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
'application/ld+json' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -325,7 +333,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
'description' => 'The new Dummy resource',
@@ -335,7 +343,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
'description' => 'Dummy resource created',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
'links' => [
@@ -354,7 +362,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -415,6 +423,10 @@ public function testNormalizeWithNameConverter(): void
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -440,7 +452,8 @@ public function testNormalizeWithNameConverter(): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -469,7 +482,7 @@ public function testNormalizeWithNameConverter(): void
'description' => 'Dummy resource response',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -480,7 +493,7 @@ public function testNormalizeWithNameConverter(): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'properties' => [
@@ -549,6 +562,10 @@ public function testNormalizeWithApiKeysEnabled(): void
],
];
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -574,7 +591,8 @@ public function testNormalizeWithApiKeysEnabled(): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -604,7 +622,7 @@ public function testNormalizeWithApiKeysEnabled(): void
'description' => 'Dummy resource response',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -615,7 +633,7 @@ public function testNormalizeWithApiKeysEnabled(): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'properties' => [
@@ -690,6 +708,10 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -715,7 +737,8 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -749,7 +772,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
'application/ld+json' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -763,7 +786,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
'description' => 'The new Dummy resource',
@@ -773,7 +796,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
'description' => 'Dummy resource created',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -800,7 +823,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
'description' => 'Dummy resource response',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -813,7 +836,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
'description' => 'The updated Dummy resource',
@@ -832,7 +855,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
'description' => 'Dummy resource updated',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/'.$ref],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-'.$ref],
],
],
],
@@ -844,7 +867,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -855,7 +878,7 @@ public function testNormalizeWithOnlyNormalizationGroups(): void
]),
],
]),
- $ref => new \ArrayObject([
+ 'application-ld+json-'.$ref => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -904,6 +927,10 @@ public function testNormalizeWithOpenApiDefinitionName(): void
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -929,7 +956,8 @@ public function testNormalizeWithOpenApiDefinitionName(): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -958,7 +986,7 @@ public function testNormalizeWithOpenApiDefinitionName(): void
'description' => 'Dummy resource response',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy-Read'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy-Read'],
],
],
],
@@ -969,7 +997,7 @@ public function testNormalizeWithOpenApiDefinitionName(): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy-Read' => new \ArrayObject([
+ 'application-ld+json-Dummy-Read' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -1026,6 +1054,10 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -1051,7 +1083,8 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -1085,7 +1118,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
'application/ld+json' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -1098,7 +1131,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
'description' => 'The new Dummy resource',
@@ -1109,7 +1142,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
'description' => 'Dummy resource created',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -1134,7 +1167,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
'description' => 'Dummy resource response',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -1147,7 +1180,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy-dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy-dummy'],
],
],
'description' => 'The updated Dummy resource',
@@ -1166,7 +1199,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
'description' => 'Dummy resource updated',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -1178,7 +1211,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -1189,7 +1222,7 @@ public function testNormalizeWithOnlyDenormalizationGroups(): void
]),
],
]),
- 'Dummy-dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy-dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -1247,6 +1280,10 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -1272,7 +1309,8 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -1306,7 +1344,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
'application/ld+json' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -1319,7 +1357,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
'description' => 'The new Dummy resource',
@@ -1330,7 +1368,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
'description' => 'Dummy resource created',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -1355,7 +1393,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
'description' => 'Dummy resource response',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -1368,7 +1406,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy-dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy-dummy'],
],
],
'description' => 'The updated Dummy resource',
@@ -1387,7 +1425,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
'description' => 'Dummy resource updated',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy-dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy-dummy'],
],
],
],
@@ -1399,7 +1437,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -1410,7 +1448,7 @@ public function testNormalizeWithNormalizationAndDenormalizationGroups(): void
]),
],
]),
- 'Dummy-dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy-dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -1724,17 +1762,20 @@ public function testNormalizeWithNestedNormalizationGroups(): void
$propertyNameCollectionFactoryProphecy->create(Dummy::class)->shouldBeCalled()->willReturn(new PropertyNameCollection(['name']));
$propertyNameCollectionFactoryProphecy->create(RelatedDummy::class, ['serializer_groups' => $groups])->shouldBeCalled(1)->willReturn(new PropertyNameCollection(['name']));
+ $formats = self::OPERATION_FORMATS;
+ $formats['output_formats']['json-api'] = ['application/vnd.api+json'];
+
$dummyMetadata = new ResourceMetadata(
'Dummy',
'This is a dummy.',
'http://schema.example.com/Dummy',
[
- 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS,
- 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + self::OPERATION_FORMATS,
+ 'get' => ['method' => 'GET'] + $formats,
+ 'put' => ['method' => 'PUT', 'normalization_context' => [AbstractNormalizer::GROUPS => $groups]] + $formats,
],
[
- 'get' => ['method' => 'GET'] + self::OPERATION_FORMATS,
- 'post' => ['method' => 'POST'] + self::OPERATION_FORMATS,
+ 'get' => ['method' => 'GET'] + $formats,
+ 'post' => ['method' => 'POST'] + $formats,
]
);
@@ -1762,6 +1803,12 @@ public function testNormalizeWithNestedNormalizationGroups(): void
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/ld+json' => new HydraDefinitionNormalizer(),
+ 'application/vnd.api+json' => new JsonApiDefinitionNormalizer(),
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -1787,7 +1834,8 @@ public function testNormalizeWithNestedNormalizationGroups(): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -1821,7 +1869,13 @@ public function testNormalizeWithNestedNormalizationGroups(): void
'application/ld+json' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
+ ],
+ ],
+ 'application/vnd.api+json' => [
+ 'schema' => [
+ 'type' => 'array',
+ 'items' => ['$ref' => '#/components/schemas/application-vnd.api%2Bjson-Dummy'],
],
],
],
@@ -1834,7 +1888,10 @@ public function testNormalizeWithNestedNormalizationGroups(): void
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
+ ],
+ 'application/vnd.api+json' => [
+ 'schema' => ['$ref' => '#/components/schemas/application-vnd.api%2Bjson-Dummy'],
],
],
'description' => 'The new Dummy resource',
@@ -1845,7 +1902,10 @@ public function testNormalizeWithNestedNormalizationGroups(): void
'description' => 'Dummy resource created',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
+ ],
+ 'application/vnd.api+json' => [
+ 'schema' => ['$ref' => '#/components/schemas/application-vnd.api%2Bjson-Dummy'],
],
],
],
@@ -1870,7 +1930,10 @@ public function testNormalizeWithNestedNormalizationGroups(): void
'description' => 'Dummy resource response',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
+ ],
+ 'application/vnd.api+json' => [
+ 'schema' => ['$ref' => '#/components/schemas/application-vnd.api%2Bjson-Dummy'],
],
],
],
@@ -1883,7 +1946,10 @@ public function testNormalizeWithNestedNormalizationGroups(): void
'requestBody' => [
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
+ ],
+ 'application/vnd.api+json' => [
+ 'schema' => ['$ref' => '#/components/schemas/application-vnd.api%2Bjson-Dummy'],
],
],
'description' => 'The updated Dummy resource',
@@ -1902,7 +1968,10 @@ public function testNormalizeWithNestedNormalizationGroups(): void
'description' => 'Dummy resource updated',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/'.$ref],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-'.$ref],
+ ],
+ 'application/vnd.api+json' => [
+ 'schema' => ['$ref' => '#/components/schemas/application-vnd.api%2Bjson-'.$ref],
],
],
],
@@ -1914,41 +1983,187 @@ public function testNormalizeWithNestedNormalizationGroups(): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
'properties' => [
- 'name' => new \ArrayObject([
- 'type' => 'string',
- 'description' => 'This is a name.',
- ]),
+ 'hydra:member' => [
+ 'type' => 'object',
+ 'properties' => [
+ '@type' => [
+ 'type' => 'string',
+ ],
+ '@id' => [
+ 'type' => 'integer',
+ ],
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ ],
+ ],
],
]),
- $ref => new \ArrayObject([
+ 'application-ld+json-'.$ref => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
'properties' => [
- 'name' => new \ArrayObject([
- 'type' => 'string',
- 'description' => 'This is a name.',
- ]),
- 'relatedDummy' => new \ArrayObject([
- 'description' => 'This is a related dummy \o/.',
- '$ref' => '#/components/schemas/'.$relatedDummyRef,
- ]),
+ 'hydra:member' => [
+ 'type' => 'object',
+ 'properties' => [
+ '@type' => [
+ 'type' => 'string',
+ ],
+ '@id' => [
+ 'type' => 'integer',
+ ],
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ 'relatedDummy' => new \ArrayObject([
+ 'description' => 'This is a related dummy \o/.',
+ '$ref' => '#/components/schemas/application-ld%2Bjson-'.$relatedDummyRef,
+ ]),
+ ],
+ ],
],
]),
- $relatedDummyRef => new \ArrayObject([
+ 'application-ld+json-'.$relatedDummyRef => new \ArrayObject([
'type' => 'object',
'description' => 'This is a related dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/RelatedDummy'],
'properties' => [
- 'name' => new \ArrayObject([
- 'type' => 'string',
- 'description' => 'This is a name.',
- ]),
+ 'hydra:member' => [
+ 'type' => 'object',
+ 'properties' => [
+ '@id' => [
+ 'type' => 'integer',
+ ],
+ '@type' => [
+ 'type' => 'string',
+ ],
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ ],
+ ],
+ ],
+ ]),
+ 'application-vnd.api+json-Dummy' => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is a dummy.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
+ 'properties' => [
+ 'data' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'type' => [
+ 'type' => 'string',
+ ],
+ 'id' => [
+ 'type' => 'integer',
+ ],
+ 'attributes' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ ],
+ ],
+ ],
+ ],
+ ],
+ ]),
+ 'application-vnd.api+json-'.$ref => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is a dummy.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
+ 'properties' => [
+ 'data' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'type' => [
+ 'type' => 'string',
+ ],
+ 'id' => [
+ 'type' => 'integer',
+ ],
+ 'attributes' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ ],
+ ],
+ 'relationships' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'relatedDummy' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'links' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'self' => [
+ 'type' => 'string',
+ ],
+ 'related' => [
+ 'type' => 'string',
+ ],
+ ],
+ ],
+ 'data' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'type' => [
+ 'type' => 'string',
+ ],
+ 'id' => [
+ 'type' => 'string',
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ]),
+ 'application-vnd.api+json-'.$relatedDummyRef => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is a related dummy.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/RelatedDummy'],
+ 'properties' => [
+ 'data' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'type' => [
+ 'type' => 'string',
+ ],
+ 'id' => [
+ 'type' => 'integer',
+ ],
+ 'attributes' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ ],
+ ],
+ ],
+ ],
],
]),
]),
@@ -1983,6 +2198,10 @@ private function normalizeWithFilters($filterLocator): void
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -2008,7 +2227,8 @@ private function normalizeWithFilters($filterLocator): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -2030,7 +2250,7 @@ private function normalizeWithFilters($filterLocator): void
'application/ld+json' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -2076,7 +2296,7 @@ private function normalizeWithFilters($filterLocator): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'properties' => [
@@ -2158,6 +2378,15 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt
$subresourceOperationFactory = new SubresourceOperationFactory($resourceMetadataFactory, $propertyNameCollectionFactory, $propertyMetadataFactory, new UnderscorePathSegmentNameGenerator());
+ $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class);
+ $formatProviderProphecy->getFormatsFromOperation(Question::class, 'get', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]);
+ $formatProviderProphecy->getFormatsFromOperation(Answer::class, 'get', OperationType::SUBRESOURCE)->willReturn(['xml' => ['text/xml']]);
+
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ 'text/xml' => new DefaultDefinitionNormalizer(), //@todo: use correct formatter
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactory,
$propertyNameCollectionFactory,
@@ -2183,7 +2412,8 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt
$formatProvider ?? [],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -2212,10 +2442,10 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt
'description' => 'Question resource response',
'content' => [
'application/json' => [
- 'schema' => ['$ref' => '#/components/schemas/Question'],
+ 'schema' => ['$ref' => '#/components/schemas/application-json-Question'],
],
'text/csv' => [
- 'schema' => ['$ref' => '#/components/schemas/Question'],
+ 'schema' => ['$ref' => '#/components/schemas/text-csv-Question'],
],
],
],
@@ -2233,7 +2463,7 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt
'description' => 'Answer resource response',
'content' => [
'text/xml' => [
- 'schema' => ['$ref' => '#/components/schemas/Answer'],
+ 'schema' => ['$ref' => '#/components/schemas/text-xml-Answer'],
],
],
],
@@ -2252,7 +2482,7 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Question' => new \ArrayObject([
+ 'application-json-Question' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a question.',
'externalDocs' => ['url' => 'http://schema.example.com/Question'],
@@ -2260,11 +2490,11 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt
'answer' => new \ArrayObject([
'type' => 'array',
'description' => 'This is a name.',
- 'items' => ['$ref' => '#/components/schemas/Answer'],
+ 'items' => ['$ref' => '#/components/schemas/application-json-Answer'],
]),
],
]),
- 'Answer' => new \ArrayObject([
+ 'application-json-Answer' => new \ArrayObject([
'type' => 'object',
'description' => 'This is an answer.',
'externalDocs' => ['url' => 'http://schema.example.com/Answer'],
@@ -2272,7 +2502,43 @@ private function doTestNormalizeWithSubResource(OperationAwareFormatsProviderInt
'content' => new \ArrayObject([
'type' => 'array',
'description' => 'This is a name.',
- 'items' => ['$ref' => '#/components/schemas/Answer'],
+ 'items' => ['$ref' => '#/components/schemas/application-json-Answer'],
+ ]),
+ ],
+ ]),
+ 'text-xml-Answer' => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is an answer.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/Answer'],
+ 'properties' => [
+ 'content' => new \ArrayObject([
+ 'type' => 'array',
+ 'description' => 'This is a name.',
+ 'items' => ['$ref' => '#/components/schemas/text-xml-Answer'],
+ ]),
+ ],
+ ]),
+ 'text-csv-Question' => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is a question.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/Question'],
+ 'properties' => [
+ 'answer' => new \ArrayObject([
+ 'type' => 'array',
+ 'description' => 'This is a name.',
+ 'items' => ['$ref' => '#/components/schemas/text-csv-Answer'],
+ ]),
+ ],
+ ]),
+ 'text-csv-Answer' => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is an answer.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/Answer'],
+ 'properties' => [
+ 'content' => new \ArrayObject([
+ 'type' => 'array',
+ 'description' => 'This is a name.',
+ 'items' => ['$ref' => '#/components/schemas/text-csv-Answer'],
]),
],
]),
@@ -2308,6 +2574,10 @@ public function testNormalizeWithPropertyOpenApiContext(): void
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -2333,7 +2603,8 @@ public function testNormalizeWithPropertyOpenApiContext(): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -2363,7 +2634,7 @@ public function testNormalizeWithPropertyOpenApiContext(): void
'description' => 'Dummy resource response',
'content' => [
'application/ld+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -2374,7 +2645,7 @@ public function testNormalizeWithPropertyOpenApiContext(): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -2424,6 +2695,10 @@ public function testNormalizeWithPaginationClientEnabled(): void
$operationPathResolver = new CustomOperationPathResolver(new OperationPathResolver(new UnderscorePathSegmentNameGenerator()));
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -2449,7 +2724,8 @@ public function testNormalizeWithPaginationClientEnabled(): void
[],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -2489,7 +2765,7 @@ public function testNormalizeWithPaginationClientEnabled(): void
'application/ld+json' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/application-ld%2Bjson-Dummy'],
],
],
],
@@ -2500,7 +2776,7 @@ public function testNormalizeWithPaginationClientEnabled(): void
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-ld+json-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
@@ -2572,6 +2848,18 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw
$operationPathResolver = new OperationPathResolver(new UnderscorePathSegmentNameGenerator());
+ $formatProviderProphecy = $this->prophesize(OperationAwareFormatsProviderInterface::class);
+ $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::COLLECTION)->willReturn(['xml' => ['application/xml', 'text/xml']]);
+ $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'post', OperationType::COLLECTION)->willReturn(['xml' => ['text/xml'], 'csv' => ['text/csv']]);
+ $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'get', OperationType::ITEM)->willReturn(['jsonapi' => ['application/vnd.api+json']]);
+ $formatProviderProphecy->getFormatsFromOperation(Dummy::class, 'put', OperationType::ITEM)->willReturn(['json' => ['application/json'], 'csv' => ['text/csv']]);
+
+ $schemaFormatterFactory = new ChainSchemaFormatter([
+ 'application/ld+json' => new HydraDefinitionNormalizer(),
+ 'application/vnd.api+json' => new JsonApiDefinitionNormalizer(),
+ 'application/json' => new DefaultDefinitionNormalizer(),
+ ]);
+
$normalizer = new DocumentationNormalizer(
$resourceMetadataFactoryProphecy->reveal(),
$propertyNameCollectionFactoryProphecy->reveal(),
@@ -2596,7 +2884,8 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw
$formatsProvider ?? [],
false,
'pagination',
- ['spec_version' => 3]
+ ['spec_version' => 3],
+ $schemaFormatterFactory
);
$expected = [
@@ -2620,13 +2909,13 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw
'application/xml' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/application-xml-Dummy'],
],
],
'text/xml' => [
'schema' => [
'type' => 'array',
- 'items' => ['$ref' => '#/components/schemas/Dummy'],
+ 'items' => ['$ref' => '#/components/schemas/text-xml-Dummy'],
],
],
],
@@ -2640,10 +2929,10 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw
'requestBody' => [
'content' => [
'text/xml' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/text-xml-Dummy'],
],
'text/csv' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/text-csv-Dummy'],
],
],
'description' => 'The new Dummy resource',
@@ -2653,10 +2942,10 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw
'description' => 'Dummy resource created',
'content' => [
'text/xml' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/text-xml-Dummy'],
],
'text/csv' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/text-csv-Dummy'],
],
],
'links' => [
@@ -2690,7 +2979,7 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw
'description' => 'Dummy resource response',
'content' => [
'application/vnd.api+json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-vnd.api%2Bjson-Dummy'],
],
],
],
@@ -2712,10 +3001,10 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw
'requestBody' => [
'content' => [
'application/json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-json-Dummy'],
],
'text/csv' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/text-csv-Dummy'],
],
],
'description' => 'The updated Dummy resource',
@@ -2725,10 +3014,10 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw
'description' => 'Dummy resource updated',
'content' => [
'application/json' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/application-json-Dummy'],
],
'text/csv' => [
- 'schema' => ['$ref' => '#/components/schemas/Dummy'],
+ 'schema' => ['$ref' => '#/components/schemas/text-csv-Dummy'],
],
],
],
@@ -2740,7 +3029,89 @@ private function doNormalizeWithCustomFormatsDefinedAtOperationLevel(OperationAw
]),
'components' => [
'schemas' => new \ArrayObject([
- 'Dummy' => new \ArrayObject([
+ 'application-json-Dummy' => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is a dummy.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
+ 'properties' => [
+ 'id' => new \ArrayObject([
+ 'type' => 'integer',
+ 'description' => 'This is an id.',
+ 'readOnly' => true,
+ ]),
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ ],
+ ]),
+ 'application-vnd.api+json-Dummy' => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is a dummy.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
+ 'properties' => [
+ 'data' => [
+ 'type' => 'object',
+ 'properties' => [
+ 'type' => [
+ 'type' => 'string',
+ ],
+ 'id' => new \ArrayObject([
+ 'type' => 'integer',
+ 'readOnly' => true,
+ 'description' => 'This is an id.',
+ ]),
+ 'attributes' => [
+ 'type' => 'object',
+ 'properties' => [
+ '_id' => new \ArrayObject([
+ 'type' => 'integer',
+ 'description' => 'This is an id.',
+ 'readOnly' => true,
+ ]),
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ ],
+ ],
+ ],
+ ],
+ ],
+ ]),
+ 'application-xml-Dummy' => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is a dummy.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
+ 'properties' => [
+ 'id' => new \ArrayObject([
+ 'type' => 'integer',
+ 'description' => 'This is an id.',
+ 'readOnly' => true,
+ ]),
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ ],
+ ]),
+ 'text-xml-Dummy' => new \ArrayObject([
+ 'type' => 'object',
+ 'description' => 'This is a dummy.',
+ 'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],
+ 'properties' => [
+ 'id' => new \ArrayObject([
+ 'type' => 'integer',
+ 'description' => 'This is an id.',
+ 'readOnly' => true,
+ ]),
+ 'name' => new \ArrayObject([
+ 'type' => 'string',
+ 'description' => 'This is a name.',
+ ]),
+ ],
+ ]),
+ 'text-csv-Dummy' => new \ArrayObject([
'type' => 'object',
'description' => 'This is a dummy.',
'externalDocs' => ['url' => 'http://schema.example.com/Dummy'],