vendor/api-platform/core/src/Documentation/Action/DocumentationAction.php line 125

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the API Platform project.
  4.  *
  5.  * (c) Kévin Dunglas <dunglas@gmail.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. declare(strict_types=1);
  11. namespace ApiPlatform\Documentation\Action;
  12. use ApiPlatform\Documentation\Documentation;
  13. use ApiPlatform\Documentation\DocumentationInterface;
  14. use ApiPlatform\Metadata\Get;
  15. use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
  16. use ApiPlatform\Metadata\Util\ContentNegotiationTrait;
  17. use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
  18. use ApiPlatform\OpenApi\OpenApi;
  19. use ApiPlatform\OpenApi\Serializer\ApiGatewayNormalizer;
  20. use ApiPlatform\OpenApi\Serializer\LegacyOpenApiNormalizer;
  21. use ApiPlatform\OpenApi\Serializer\OpenApiNormalizer;
  22. use ApiPlatform\State\ProcessorInterface;
  23. use ApiPlatform\State\ProviderInterface;
  24. use Negotiation\Negotiator;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\Response;
  27. /**
  28.  * Generates the API documentation.
  29.  *
  30.  * @author Amrouche Hamza <hamza.simperfit@gmail.com>
  31.  */
  32. final class DocumentationAction
  33. {
  34.     use ContentNegotiationTrait;
  35.     public function __construct(
  36.         private readonly ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory,
  37.         private readonly string $title '',
  38.         private readonly string $description '',
  39.         private readonly string $version '',
  40.         private readonly ?OpenApiFactoryInterface $openApiFactory null,
  41.         private readonly ?ProviderInterface $provider null,
  42.         private readonly ?ProcessorInterface $processor null,
  43.         ?Negotiator $negotiator null,
  44.         private readonly array $documentationFormats = [OpenApiNormalizer::JSON_FORMAT => ['application/vnd.openapi+json'], OpenApiNormalizer::FORMAT => ['application/json']]
  45.     ) {
  46.         $this->negotiator $negotiator ?? new Negotiator();
  47.     }
  48.     /**
  49.      * @return DocumentationInterface|OpenApi|Response
  50.      */
  51.     public function __invoke(?Request $request null)
  52.     {
  53.         if (null === $request) {
  54.             return new Documentation($this->resourceNameCollectionFactory->create(), $this->title$this->description$this->version);
  55.         }
  56.         $context = [
  57.             'api_gateway' => $request->query->getBoolean(ApiGatewayNormalizer::API_GATEWAY),
  58.             'base_url' => $request->getBaseUrl(),
  59.             'spec_version' => (string) $request->query->get(LegacyOpenApiNormalizer::SPEC_VERSION),
  60.         ];
  61.         $request->attributes->set('_api_normalization_context'$request->attributes->get('_api_normalization_context', []) + $context);
  62.         $format $this->getRequestFormat($request$this->documentationFormats);
  63.         if (null !== $this->openApiFactory && ('html' === $format || OpenApiNormalizer::FORMAT === $format || OpenApiNormalizer::JSON_FORMAT === $format || OpenApiNormalizer::YAML_FORMAT === $format)) {
  64.             return $this->getOpenApiDocumentation($context$format$request);
  65.         }
  66.         return $this->getHydraDocumentation($context$request);
  67.     }
  68.     /**
  69.      * @param array<string,mixed> $context
  70.      */
  71.     private function getOpenApiDocumentation(array $contextstring $formatRequest $request): OpenApi|Response
  72.     {
  73.         if ($this->provider && $this->processor) {
  74.             $context['request'] = $request;
  75.             $operation = new Get(
  76.                 class: OpenApi::class,
  77.                 readtrue,
  78.                 serializetrue,
  79.                 provider: fn () => $this->openApiFactory->__invoke($context),
  80.                 normalizationContext: [
  81.                     ApiGatewayNormalizer::API_GATEWAY => $context['api_gateway'] ?? null,
  82.                     LegacyOpenApiNormalizer::SPEC_VERSION => $context['spec_version'] ?? null,
  83.                 ],
  84.                 outputFormats$this->documentationFormats
  85.             );
  86.             if ('html' === $format) {
  87.                 $operation $operation->withProcessor('api_platform.swagger_ui.processor')->withWrite(true);
  88.             }
  89.             if ('json' === $format) {
  90.                 trigger_deprecation('api-platform/core''3.2''The "json" format is too broad, use "jsonopenapi" instead.');
  91.             }
  92.             return $this->processor->process($this->provider->provide($operation, [], $context), $operation, [], $context);
  93.         }
  94.         return $this->openApiFactory->__invoke($context);
  95.     }
  96.     /**
  97.      * TODO: the logic behind the Hydra Documentation is done in a ApiPlatform\Hydra\Serializer\DocumentationNormalizer.
  98.      * We should transform this to a provider, it'd improve performances also by a bit.
  99.      *
  100.      * @param array<string,mixed> $context
  101.      */
  102.     private function getHydraDocumentation(array $contextRequest $request): DocumentationInterface|Response
  103.     {
  104.         if ($this->provider && $this->processor) {
  105.             $context['request'] = $request;
  106.             $operation = new Get(
  107.                 class: Documentation::class,
  108.                 readtrue,
  109.                 serializetrue,
  110.                 provider: fn () => new Documentation($this->resourceNameCollectionFactory->create(), $this->title$this->description$this->version)
  111.             );
  112.             return $this->processor->process($this->provider->provide($operation, [], $context), $operation, [], $context);
  113.         }
  114.         return new Documentation($this->resourceNameCollectionFactory->create(), $this->title$this->description$this->version);
  115.     }
  116. }