Skip to content

Commit

Permalink
feat(#2212): support type info component (#2349)
Browse files Browse the repository at this point in the history
## Description

Adds support for Symfony's [type-info
component](https://symfony.com/doc/current/components/type_info.html)
for describing properties.

Closes #2212, Fixes
#2323, Fixes
#1542, Fixes
#2272

## What type of PR is this? (check all applicable)
- [ ] Bug Fix
- [x] Feature
- [ ] Refactor
- [ ] Deprecation
- [ ] Breaking Change
- [x] Documentation Update
- [ ] CI

## Checklist
- [x] I have made corresponding changes to the documentation (`docs/`)
- [x] I have made corresponding changes to the changelog
(`CHANGELOG.md`)
  • Loading branch information
DjordyKoert authored Jan 18, 2025
1 parent a2497e1 commit 86d1a11
Show file tree
Hide file tree
Showing 67 changed files with 2,171 additions and 39 deletions.
8 changes: 4 additions & 4 deletions .doctor-rst.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ rules:

# master
versionadded_directive_major_version:
major_version: 6
major_version: 7

versionadded_directive_min_version:
min_version: '6.0'
min_version: '7.0'

deprecated_directive_major_version:
major_version: 5
major_version: 6

deprecated_directive_min_version:
min_version: '5.0'
min_version: '6.0'

# do not report as violation
whitelist:
Expand Down
22 changes: 16 additions & 6 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,34 @@

declare(strict_types=1);

/*
* This file is part of the NelmioApiDocBundle package.
*
* (c) Nelmio
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

$finder = (new PhpCsFixer\Finder())
->in(__DIR__)
->exclude('var')
->exclude('tests/Functional/cache');
->exclude('tests/Functional/cache')
->exclude('tests/Functional/ModelDescriber/Fixtures');

return (new PhpCsFixer\Config())
->setRules([
'@Symfony' => true,
'@PHP84Migration' => true,
'header_comment' => [
'header' => <<<HEADER
This file is part of the NelmioApiDocBundle package.
This file is part of the NelmioApiDocBundle package.
(c) Nelmio
(c) Nelmio
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
HEADER
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
HEADER
],
'trailing_comma_in_multiline' => false,
])
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# CHANGELOG

## 4.35.0
* Added support for the symfony/type-info component
```yaml
nelmio_api_doc:
type_info: true
```
## 4.34.0
* Changed minimum Symfony version for 7.x from 7.0 to 7.1
Expand Down
59 changes: 59 additions & 0 deletions config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,65 @@
<service id="nelmio_api_doc.swagger.processor.nullable_property" class="Nelmio\ApiDocBundle\Processor\NullablePropertyProcessor">
<tag name="nelmio_api_doc.swagger.processor" />
</service>

<!-- Type describers (symfony/type-info) -->
<service id="nelmio_api_doc.type_describer.chain" class="Nelmio\ApiDocBundle\TypeDescriber\ChainDescriber" public="false">
<argument type="tagged" tag="nelmio_api_doc.type_describer" />

<tag name="nelmio_api_doc.type_describer" priority="1000" />
</service>

<service id="nelmio_api_doc.type_describer.array" class="Nelmio\ApiDocBundle\TypeDescriber\ArrayDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.bool" class="Nelmio\ApiDocBundle\TypeDescriber\BoolDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.class" class="Nelmio\ApiDocBundle\TypeDescriber\ClassDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.dictionary" class="Nelmio\ApiDocBundle\TypeDescriber\DictionaryDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.float" class="Nelmio\ApiDocBundle\TypeDescriber\FloatDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.integer" class="Nelmio\ApiDocBundle\TypeDescriber\IntegerDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.intersection" class="Nelmio\ApiDocBundle\TypeDescriber\IntersectionDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.list" class="Nelmio\ApiDocBundle\TypeDescriber\ListDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.mixed" class="Nelmio\ApiDocBundle\TypeDescriber\MixedDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.nullable" class="Nelmio\ApiDocBundle\TypeDescriber\NullableDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-950" />
</service>

<service id="nelmio_api_doc.type_describer.object" class="Nelmio\ApiDocBundle\TypeDescriber\ObjectDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.string" class="Nelmio\ApiDocBundle\TypeDescriber\StringDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>

<service id="nelmio_api_doc.type_describer.union" class="Nelmio\ApiDocBundle\TypeDescriber\UnionDescriber" public="false">
<tag name="nelmio_api_doc.type_describer" priority="-1000" />
</service>
</services>

</container>
83 changes: 82 additions & 1 deletion docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,85 @@ Note, however, that a ``type="object"`` will still read all a models properties.
class SomeCollection implements \IteratorAggregate
{
// ...
}
}
PropertyInfo component was unable to guess the type
---------------------------------------------------

Q: I have a property that is not recognized. How can I specify the type?

.. tip::

Enable the `TypeInfo component`_ in your configuration to improve automatic type guessing:

.. code-block:: yaml
nelmio_api_doc:
type_info: true
# ...
.. versionadded:: 7.2

The `TypeInfo component`_ was introduced as a stable feature in Symfony 7.2.

A: If you want to customize the documentation of an object's property, you can use the ``#[OA\Property]`` attribute or annotate the property with ``@var``::

.. configuration-block::

.. code-block:: php-annotations
use Nelmio\ApiDocBundle\Attribute\Model;
use OpenApi\Annotations as OA;
class User
{
/**
* @var int
* @OA\Property(description="The unique identifier of the user.")
*/
public $id;
/**
* @OA\Property(type="string", maxLength=255)
*/
public $username;
/**
* @OA\Property(ref=@Model(type=User::class))
*/
public $friend;
/**
* @OA\Property(description="This is my coworker!")
*/
public setCoworker(User $coworker) {
// ...
}
}
.. code-block:: php-attributes
use Nelmio\ApiDocBundle\Attribute\Model;
use OpenApi\Attributes as OA;
class User
{
/**
* @var int
*/
#[OA\Property(description: 'The unique identifier of the user.')]
public $id;
#[OA\Property(type: 'string', maxLength: 255)]
public $username;
#[OA\Property(ref: new Model(type: User::class))]
public $friend;
#[OA\Property(description: 'This is my coworker!')]
public setCoworker(User $coworker) {
// ...
}
}
.. _`TypeInfo component`: https://symfony.com/doc/current/components/type_info.html
17 changes: 16 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,20 @@ General PHP objects
When using the JMS serializer combined with `willdurand/Hateoas`_ (and the `BazingaHateoasBundle`_),
HATEOAS metadata are automatically extracted

.. tip::

Enable the `TypeInfo component`_ in your configuration to improve automatic type guessing:

.. code-block:: yaml
nelmio_api_doc:
type_info: true
# ...
.. versionadded:: 7.2

The `TypeInfo component`_ was introduced as a stable feature in Symfony 7.2.

If you want to customize the documentation of an object's property, you can use ``#[OA\Property]``::


Expand Down Expand Up @@ -601,12 +615,13 @@ If you need more complex features, take a look at:
alternative_names
customization
commands
faq
security
symfony_attributes
faq

.. _`SwaggerPHP examples`: https://github.com/zircote/swagger-php/tree/master/Examples
.. _`Symfony PropertyInfo component`: https://symfony.com/doc/current/components/property_info.html
.. _`TypeInfo component`: https://symfony.com/doc/current/components/type_info.html
.. _`willdurand/Hateoas`: https://github.com/willdurand/Hateoas
.. _`BazingaHateoasBundle`: https://github.com/willdurand/BazingaHateoasBundle
.. _`JMS serializer`: https://jmsyst.com/libs/serializer
Expand Down
14 changes: 0 additions & 14 deletions docs/symfony_attributes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ MapQueryString

Using the `Symfony MapQueryString`_ attribute allows NelmioApiDocBundle to automatically generate your query parameter documentation for your endpoint from your object.

.. versionadded:: 6.3

The :class:`Symfony\\Component\\HttpKernel\\Attribute\\MapQueryString` attribute was introduced in Symfony 6.3.

Modify generated documentation
~~~~~~~

Expand All @@ -35,11 +31,6 @@ MapQueryParameter

Using the `Symfony MapQueryParameter`_ attribute allows NelmioApiDocBundle to automatically generate your query parameter documentation for your endpoint.

.. versionadded:: 6.3

The :class:`Symfony\\Component\\HttpKernel\\Attribute\\MapQueryParameter` attribute was introduced in Symfony 6.3.


Modify generated documentation
~~~~~~~

Expand All @@ -59,11 +50,6 @@ MapRequestPayload

Using the `Symfony MapRequestPayload`_ attribute allows NelmioApiDocBundle to automatically generate your request body documentation for your endpoint.

.. versionadded:: 6.3

The :class:`Symfony\\Component\\HttpKernel\\Attribute\\MapRequestPayload` attribute was introduced in Symfony 6.3.


Modify generated documentation
~~~~~~~

Expand Down
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ parameters:
count: 1
path: src/Describer/ExternalDocDescriber.php

-
message: "#^Method Nelmio\\\\ApiDocBundle\\\\PropertyDescriber\\\\PropertyDescriberInterface\\:\\:describe\\(\\) invoked with 5 parameters, 2\\-3 required\\.$#"
count: 1
path: src/ModelDescriber/ObjectModelDescriber.php

-
message: "#^Method Nelmio\\\\ApiDocBundle\\\\PropertyDescriber\\\\ArrayPropertyDescriber\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
Expand Down
4 changes: 4 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public function getConfigTreeBuilder(): TreeBuilder

$rootNode
->children()
->booleanNode('type_info')
->info('Use the symfony/type-info component for determining types.')
->defaultFalse()
->end()
->booleanNode('use_validation_groups')
->info('If true, `groups` passed to @Model annotations will be used to limit validation constraints')
->defaultFalse()
Expand Down
5 changes: 5 additions & 0 deletions src/DependencyInjection/NelmioApiDocExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,11 @@ public function load(array $configs, ContainerBuilder $container): void
array_map(function ($area) { return new Reference(sprintf('nelmio_api_doc.generator.%s', $area)); }, array_keys($config['areas']))
));

if (true === $config['type_info']) {
$container->getDefinition('nelmio_api_doc.model_describers.object')
->setArgument(2, new Reference('nelmio_api_doc.type_describer.chain'));
}

$container->getDefinition('nelmio_api_doc.model_describers.object')
->setArgument(3, $config['media_types']);

Expand Down
Loading

0 comments on commit 86d1a11

Please sign in to comment.