Skip to content

Commit

Permalink
Merge branch 'master' into conventional-commits
Browse files Browse the repository at this point in the history
  • Loading branch information
DjordyKoert committed Jun 12, 2024
2 parents 24083cf + c21aead commit 18a7112
Show file tree
Hide file tree
Showing 38 changed files with 692 additions and 94 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
CHANGELOG
=========

4.26.0
-----
* Add ability to configure UI through configuration
```yaml
nelmio_api_doc:
html_config:
assets_mode: bundle
redocly_config:
expandResponses: '200,201'
hideDownloadButton: true
swagger_ui_config:
deepLinking: true
```

4.25.0
-----
* Added support for [JMS @Discriminator](https://jmsyst.com/libs/serializer/master/reference/annotations#discriminator) annotation/attribute
Expand Down
1 change: 1 addition & 0 deletions config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
</service>
<service id="nelmio_api_doc.render_docs.html" class="Nelmio\ApiDocBundle\Render\Html\HtmlOpenApiRenderer" public="false">
<argument type="service" id="twig" />
<argument type="collection" />
</service>
<service id="nelmio_api_doc.render_docs.html.asset" class="Nelmio\ApiDocBundle\Render\Html\GetNelmioAsset" public="false">
<argument type="service" id="twig.extension.assets" />
Expand Down
2 changes: 2 additions & 0 deletions docs/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ or configure UI configuration, use the ``--html-config`` option.
- ``server_url`` - API url, useful if static documentation is not hosted on API url
- ``swagger_ui_config`` - `configure Swagger UI`_
- ``"supportedSubmitMethods":[]`` disables the sandbox
- ``redocly_config`` - `configure Redocly`_

.. code-block:: bash
$ php bin/console nelmio:apidoc:dump --format=html --html-config '{"assets_mode":"offline","server_url":"https://example.com","swagger_ui_config":{"supportedSubmitMethods":[]}}' > api.html
.. _`configure Swagger UI`: https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/
.. _`configure Redocly`: https://redocly.com/docs/redoc/config/
28 changes: 23 additions & 5 deletions docs/customization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,34 @@ Just create a file ``templates/bundles/NelmioApiDocBundle/SwaggerUi/index.html.t
{% extends '@!NelmioApiDoc/SwaggerUi/index.html.twig' %}
{#
Change swagger UI configuration
Change Swagger UI configuration
All parameters are explained on Swagger UI website:
https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/
#}
{% block swagger_initialization %}
<script type="text/javascript">
window.onload = loadSwaggerUI({
defaultModelsExpandDepth: -1,
deepLinking: true,
});
window.onload = () => {
loadSwaggerUI({
defaultModelsExpandDepth: -1,
deepLinking: true,
});
};
</script>
{% endblock %}
{#
Change Redocly configuration
All parameters are explained on Redocly website:
https://redocly.com/docs/redoc/config/
#}
{% block swagger_initialization %}
<script type="text/javascript">
window.onload = () => {
loadRedocly({
expandResponses: '200,201',
hideDownloadButton: true,
});
};
</script>
{% endblock %}
Expand Down
10 changes: 0 additions & 10 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
parameters:
ignoreErrors:
-
message: "#^Property Nelmio\\\\ApiDocBundle\\\\Annotation\\\\Model\\:\\:\\$_required type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Annotation/Model.php

-
message: "#^Property Nelmio\\\\ApiDocBundle\\\\Annotation\\\\Security\\:\\:\\$_required type has no value type specified in iterable type array\\.$#"
count: 1
path: src/Annotation/Security.php

-
message: "#^Only booleans are allowed in an if condition, mixed given\\.$#"
count: 1
Expand Down
6 changes: 3 additions & 3 deletions public/init-redocly-ui.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

window.onload = () => {
function loadRedocly(userOptions = {}) {
const data = JSON.parse(document.getElementById('swagger-data').innerText);

Redoc.init(data.spec, {}, document.getElementById('swagger-ui'));
};
Redoc.init(data.spec, userOptions, document.getElementById('swagger-ui'));
}
9 changes: 3 additions & 6 deletions src/ApiDocGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,9 @@ final class ApiDocGenerator
/** @var iterable|ModelDescriberInterface[] */
private $modelDescribers;

/** @var CacheItemPoolInterface|null */
private $cacheItemPool;
private ?CacheItemPoolInterface $cacheItemPool;

/** @var string */
private $cacheItemId;
private string $cacheItemId;

/** @var string[] */
private $alternativeNames = [];
Expand All @@ -53,8 +51,7 @@ final class ApiDocGenerator
*/
private $openApiVersion;

/** @var Generator */
private $generator;
private Generator $generator;

/**
* @param DescriberInterface[]|iterable $describers
Expand Down
6 changes: 5 additions & 1 deletion src/Command/DumpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
* @final
*/
class DumpCommand extends Command
{
private RenderOpenApi $renderOpenApi;
Expand All @@ -28,6 +31,7 @@ class DumpCommand extends Command
private $defaultHtmlConfig = [
'assets_mode' => AssetsMode::CDN,
'swagger_ui_config' => [],
'redocly_config' => [],
];

public function __construct(RenderOpenApi $renderOpenApi)
Expand Down Expand Up @@ -67,7 +71,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$options = [];
if (RenderOpenApi::HTML === $format) {
$rawHtmlConfig = json_decode($input->getOption('html-config'), true);
$options = is_array($rawHtmlConfig) ? $rawHtmlConfig : $this->defaultHtmlConfig;
$options = is_array($rawHtmlConfig) ? $rawHtmlConfig + $this->defaultHtmlConfig : $this->defaultHtmlConfig;
} elseif (RenderOpenApi::JSON === $format) {
$options = [
'no-pretty' => $input->hasParameterOption(['--no-pretty']),
Expand Down
2 changes: 0 additions & 2 deletions src/Controller/SwaggerUiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
namespace Nelmio\ApiDocBundle\Controller;

use Nelmio\ApiDocBundle\Exception\RenderInvalidArgumentException;
use Nelmio\ApiDocBundle\Render\Html\AssetsMode;
use Nelmio\ApiDocBundle\Render\RenderOpenApi;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand All @@ -35,7 +34,6 @@ public function __invoke(Request $request, string $area = 'default'): Response
try {
$response = new Response(
$this->renderOpenApi->renderFromRequest($request, RenderOpenApi::HTML, $area, [
'assets_mode' => AssetsMode::BUNDLE,
'ui_renderer' => $this->uiRenderer,
]),
Response::HTTP_OK,
Expand Down
26 changes: 25 additions & 1 deletion src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Nelmio\ApiDocBundle\DependencyInjection;

use Nelmio\ApiDocBundle\Render\Html\AssetsMode;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

Expand Down Expand Up @@ -55,6 +56,29 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultValue(['json'])
->prototype('scalar')->end()
->end()
->arrayNode('html_config')
->info('UI configuration options')
->addDefaultsIfNotSet()
->children()
->scalarNode('assets_mode')
->defaultValue(AssetsMode::CDN)
->validate()
->ifNotInArray([AssetsMode::BUNDLE, AssetsMode::CDN, AssetsMode::OFFLINE])
->thenInvalid('Invalid assets mode %s')
->end()
->end()
->arrayNode('swagger_ui_config')
->info('https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/')
->addDefaultsIfNotSet()
->ignoreExtraKeys(false)
->end()
->arrayNode('redocly_config')
->info('https://redocly.com/docs/redoc/config/')
->addDefaultsIfNotSet()
->ignoreExtraKeys(false)
->end()
->end()
->end()
->arrayNode('areas')
->info('Filter the routes that are documented')
->defaultValue(
Expand All @@ -74,7 +98,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->ifTrue(function ($v) {
return 0 === count($v) || isset($v['path_patterns']) || isset($v['host_patterns']) || isset($v['documentation']);
})
->then(function ($v) {
->then(function ($v): array {
return ['default' => $v];
})
->end()
Expand Down
2 changes: 2 additions & 0 deletions src/DependencyInjection/NelmioApiDocExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ public function load(array $configs, ContainerBuilder $container): void

$container->removeDefinition('nelmio_api_doc.render_docs.html');
$container->removeDefinition('nelmio_api_doc.render_docs.html.asset');
} elseif (isset($config['html_config'])) {
$container->getDefinition('nelmio_api_doc.render_docs.html')->replaceArgument(1, $config['html_config']);
}

// ApiPlatform support
Expand Down
16 changes: 6 additions & 10 deletions src/Describer/OpenApiPhpDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,6 @@ public function describe(OA\OpenApi $api): void

$annotations = array_merge($annotations, $this->getAttributesAsAnnotation($method, $context));

if (0 === count($annotations) && 0 === count($classAnnotations[$declaringClass->getName()])) {
continue;
}

$implicitAnnotations = [];
$mergeProperties = new \stdClass();

Expand Down Expand Up @@ -154,14 +150,14 @@ public function describe(OA\OpenApi $api): void
$implicitAnnotations[] = $annotation;
}

if ([] === $implicitAnnotations && [] === get_object_vars($mergeProperties)) {
continue;
}

foreach ($httpMethods as $httpMethod) {
$operation = Util::getOperation($path, $httpMethod);
$operation->merge($implicitAnnotations);
$operation->mergeProperties($mergeProperties);
if ([] !== $implicitAnnotations) {
$operation->merge($implicitAnnotations);
}
if ([] !== get_object_vars($mergeProperties)) {
$operation->mergeProperties($mergeProperties);
}

if (Generator::UNDEFINED === $operation->operationId) {
$operation->operationId = $httpMethod.'_'.$routeName;
Expand Down
2 changes: 1 addition & 1 deletion src/Model/ModelRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private function generateModelName(Model $model): string
*/
private function modelToArray(Model $model): array
{
$getType = function (Type $type) use (&$getType) {
$getType = function (Type $type) use (&$getType): array {
return [
'class' => $type->getClassName(),
'built_in_type' => $type->getBuiltinType(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,14 @@ class SymfonyConstraintAnnotationReader
{
use SetsContextTrait;

/**
* @var Reader|null
*/
private $annotationsReader;
private ?Reader $annotationsReader;

/**
* @var OA\Schema
*/
private $schema;

/**
* @var bool
*/
private $useValidationGroups;
private bool $useValidationGroups;

public function __construct(?Reader $annotationsReader, bool $useValidationGroups = false)
{
Expand Down Expand Up @@ -213,7 +207,7 @@ private function getAnnotations(Context $parentContext, $reflection, ?array $val
*/
private function locateAnnotations($reflection): \Traversable
{
if (\PHP_VERSION_ID >= 80000) {
if (\PHP_VERSION_ID >= 80000 && class_exists(Constraint::class)) {
foreach ($reflection->getAttributes(Constraint::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) {
yield $attribute->newInstance();
}
Expand Down
31 changes: 31 additions & 0 deletions src/ModelDescriber/JMSModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public function describe(Model $model, OA\Schema $schema)
} catch (\ReflectionException $ignored) {
}
}
$this->checkRequiredFields($reflections, $schema, $name);
if (null !== $item->setter) {
try {
$reflections[] = new \ReflectionMethod($item->class, $item->setter);
Expand Down Expand Up @@ -397,4 +398,34 @@ private function propertyTypeUsesGroups(array $type): ?bool
return null;
}
}

/**
* Mark property as required if it is not nullable.
*
* @param array<\ReflectionProperty|\ReflectionMethod> $reflections
*/
private function checkRequiredFields(array $reflections, OA\Schema $schema, string $name): void
{
foreach ($reflections as $reflection) {
$nullable = false;
if ($reflection instanceof \ReflectionProperty) {
$type = PHP_VERSION_ID >= 70400 ? $reflection->getType() : null;
if (null !== $type && !$type->allowsNull()) {
$nullable = true;
}
} elseif ($reflection instanceof \ReflectionMethod) {
$returnType = $reflection->getReturnType();
if (null !== $returnType && !$returnType->allowsNull()) {
$nullable = true;
}
}
if ($nullable) {
$required = Generator::UNDEFINED !== $schema->required ? $schema->required : [];
$required[] = $name;

$schema->required = $required;
break;
}
}
}
}
16 changes: 6 additions & 10 deletions src/ModelDescriber/ObjectModelDescriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,16 @@ class ObjectModelDescriber implements ModelDescriberInterface, ModelRegistryAwar
use ModelRegistryAwareTrait;
use ApplyOpenApiDiscriminatorTrait;

/** @var PropertyInfoExtractorInterface */
private $propertyInfo;
/** @var ClassMetadataFactoryInterface|null */
private $classMetadataFactory;
/** @var Reader|null */
private $doctrineReader;
private PropertyInfoExtractorInterface $propertyInfo;
private ?ClassMetadataFactoryInterface $classMetadataFactory;
private ?Reader $doctrineReader;
/** @var PropertyDescriberInterface|PropertyDescriberInterface[] */
private $propertyDescriber;
/** @var string[] */
private $mediaTypes;
private array $mediaTypes;
/** @var (NameConverterInterface&AdvancedNameConverterInterface)|null */
private $nameConverter;
/** @var bool */
private $useValidationGroups;
private ?NameConverterInterface $nameConverter;
private bool $useValidationGroups;

/**
* @param PropertyDescriberInterface|PropertyDescriberInterface[] $propertyDescribers
Expand Down
Loading

0 comments on commit 18a7112

Please sign in to comment.