vendor/nelmio/api-doc-bundle/src/ApiDocGenerator.php line 63

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the NelmioApiDocBundle package.
  4. *
  5. * (c) Nelmio
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Nelmio\ApiDocBundle;
  11. use Nelmio\ApiDocBundle\Describer\DescriberInterface;
  12. use Nelmio\ApiDocBundle\Describer\ModelRegistryAwareInterface;
  13. use Nelmio\ApiDocBundle\Model\ModelRegistry;
  14. use Nelmio\ApiDocBundle\ModelDescriber\ModelDescriberInterface;
  15. use Nelmio\ApiDocBundle\OpenApiPhp\ModelRegister;
  16. use Nelmio\ApiDocBundle\OpenApiPhp\Util;
  17. use OpenApi\Analysis;
  18. use OpenApi\Annotations\OpenApi;
  19. use OpenApi\Generator;
  20. use OpenApi\Processors\ProcessorInterface;
  21. use Psr\Cache\CacheItemPoolInterface;
  22. use Psr\Log\LoggerAwareTrait;
  23. final class ApiDocGenerator
  24. {
  25. use LoggerAwareTrait;
  26. /** @var OpenApi */
  27. private $openApi;
  28. /** @var iterable|DescriberInterface[] */
  29. private $describers;
  30. /** @var iterable|ModelDescriberInterface[] */
  31. private $modelDescribers;
  32. /** @var CacheItemPoolInterface|null */
  33. private $cacheItemPool;
  34. /** @var string */
  35. private $cacheItemId;
  36. /** @var string[] */
  37. private $alternativeNames = [];
  38. /** @var string[] */
  39. private $mediaTypes = ['json'];
  40. /**
  41. * @var ?string
  42. */
  43. private $openApiVersion = null;
  44. /** @var Generator */
  45. private $generator;
  46. /**
  47. * @param DescriberInterface[]|iterable $describers
  48. * @param ModelDescriberInterface[]|iterable $modelDescribers
  49. */
  50. public function __construct($describers, $modelDescribers, CacheItemPoolInterface $cacheItemPool = null, string $cacheItemId = null, Generator $generator = null)
  51. {
  52. $this->describers = $describers;
  53. $this->modelDescribers = $modelDescribers;
  54. $this->cacheItemPool = $cacheItemPool;
  55. $this->cacheItemId = $cacheItemId ?? 'openapi_doc';
  56. $this->generator = $generator ?? new Generator($this->logger);
  57. }
  58. public function setAlternativeNames(array $alternativeNames)
  59. {
  60. $this->alternativeNames = $alternativeNames;
  61. }
  62. public function setMediaTypes(array $mediaTypes)
  63. {
  64. $this->mediaTypes = $mediaTypes;
  65. }
  66. public function setOpenApiVersion(?string $openApiVersion)
  67. {
  68. $this->openApiVersion = $openApiVersion;
  69. }
  70. public function generate(): OpenApi
  71. {
  72. if (null !== $this->openApi) {
  73. return $this->openApi;
  74. }
  75. if ($this->cacheItemPool) {
  76. $item = $this->cacheItemPool->getItem($this->cacheItemId);
  77. if ($item->isHit()) {
  78. return $this->openApi = $item->get();
  79. }
  80. }
  81. if ($this->openApiVersion) {
  82. $this->generator->setVersion($this->openApiVersion);
  83. }
  84. $this->generator->setProcessors($this->getProcessors($this->generator));
  85. $context = Util::createContext(['version' => $this->generator->getVersion()]);
  86. $this->openApi = new OpenApi(['_context' => $context]);
  87. $modelRegistry = new ModelRegistry($this->modelDescribers, $this->openApi, $this->alternativeNames);
  88. if (null !== $this->logger) {
  89. $modelRegistry->setLogger($this->logger);
  90. }
  91. foreach ($this->describers as $describer) {
  92. if ($describer instanceof ModelRegistryAwareInterface) {
  93. $describer->setModelRegistry($modelRegistry);
  94. }
  95. $describer->describe($this->openApi);
  96. }
  97. $analysis = new Analysis([], $context);
  98. $analysis->addAnnotation($this->openApi, $context);
  99. // Register model annotations
  100. $modelRegister = new ModelRegister($modelRegistry, $this->mediaTypes);
  101. $modelRegister($analysis);
  102. // Calculate the associated schemas
  103. $modelRegistry->registerSchemas();
  104. $analysis->process($this->generator->getProcessors());
  105. $analysis->validate();
  106. if (isset($item)) {
  107. $this->cacheItemPool->save($item->set($this->openApi));
  108. }
  109. return $this->openApi;
  110. }
  111. /**
  112. * Get an array of processors that will be used to process the OpenApi object.
  113. *
  114. * @param Generator $generator The generator instance to get the standard processors from
  115. *
  116. * @return array<ProcessorInterface|callable> The array of processors
  117. */
  118. private function getProcessors(Generator $generator): array
  119. {
  120. // Get the standard processors from the generator.
  121. $processors = $generator->getProcessors();
  122. // Remove OperationId processor as we use a lot of generated annotations which do not have enough information in their context
  123. // to generate these ids properly.
  124. // @see \Nelmio\ApiDocBundle\OpenApiPhp\Util::createContext
  125. foreach ($processors as $key => $processor) {
  126. if ($processor instanceof \OpenApi\Processors\OperationId) {
  127. unset($processors[$key]);
  128. }
  129. }
  130. return $processors;
  131. }
  132. }