From 16201cd3c8120fd704df4a7545cb454b395bea88 Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 13:12:00 +0200 Subject: [PATCH 01/11] rename annotations namespace --- UPGRADE-3.0.md | 2 +- UPGRADE-5.0.md | 2 ++ src/{Annotation => Attribute}/Areas.php | 2 +- src/{Annotation => Attribute}/Model.php | 2 +- src/{Annotation => Attribute}/Operation.php | 2 +- src/{Annotation => Attribute}/Security.php | 2 +- src/Describer/OpenApiPhpDescriber.php | 4 ++-- src/OpenApiPhp/ModelRegister.php | 2 +- src/Routing/FilteredRouteCollectionBuilder.php | 4 ++-- tests/Functional/Controller/ApiController.php | 8 ++++---- tests/Functional/Controller/BazingaController.php | 2 +- tests/Functional/Controller/BazingaTypedController.php | 2 +- tests/Functional/Controller/ClassApiController.php | 2 +- tests/Functional/Controller/Controller2209.php | 2 +- tests/Functional/Controller/JMSController.php | 2 +- tests/Functional/Controller/JmsOptOutController.php | 2 +- .../Functional/Controller/MapRequestPayloadController.php | 2 +- tests/Functional/Controller/OperationIdController.php | 2 +- .../Controller/PromotedPropertiesController81.php | 2 +- tests/Functional/Entity/JMSComplex.php | 2 +- tests/Functional/Entity/JMSDualComplex.php | 2 +- tests/Functional/Form/FormWithModel.php | 2 +- .../SymfonyMapRequestPayloadDescriberTest.php | 2 +- tests/Routing/FilteredRouteCollectionBuilderTest.php | 4 ++-- 24 files changed, 31 insertions(+), 29 deletions(-) rename src/{Annotation => Attribute}/Areas.php (96%) rename src/{Annotation => Attribute}/Model.php (97%) rename src/{Annotation => Attribute}/Operation.php (89%) rename src/{Annotation => Attribute}/Security.php (95%) diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md index f720e2737..07d643764 100644 --- a/UPGRADE-3.0.md +++ b/UPGRADE-3.0.md @@ -17,7 +17,7 @@ First, copy this command in ``src/AppBundle/Command/SwaggerDocblockConvertComman // src/AppBundle/Command/SwaggerDocblockConvertCommand.php namespace AppBundle\Command; -use Nelmio\ApiDocBundle\Annotation\ApiDoc; +use Nelmio\ApiDocBundle\Attribute\ApiDoc; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index fe5e4a57f..abdcff0c7 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -25,3 +25,5 @@ This causes the following breaking changes in classes that used annotations: - BC BREAK: Removed 2nd parameter `?Reader $annotationReader` from `Nelmio\ApiDocBundle\ModelDescriber\ObjectModelDescriber::__construct()` - BC BREAK: Removed 1st parameter `?Reader $annotationReader` from `Nelmio\ApiDocBundle\RouteDescriber\FosRestDescriber::__construct()` - BC BREAK: Removed 1st parameter `?Reader $annotationReader` from `Nelmio\ApiDocBundle\Routing\FilteredRouteCollectionBuilder::__construct()` + +## BC BREAK: `Nelmio\ApiDocBundle\Annotation` namespace has been moved to `Nelmio\ApiDocBundle\Attribute` \ No newline at end of file diff --git a/src/Annotation/Areas.php b/src/Attribute/Areas.php similarity index 96% rename from src/Annotation/Areas.php rename to src/Attribute/Areas.php index f90983576..0d004c0e7 100644 --- a/src/Annotation/Areas.php +++ b/src/Attribute/Areas.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Nelmio\ApiDocBundle\Annotation; +namespace Nelmio\ApiDocBundle\Attribute; #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)] final class Areas diff --git a/src/Annotation/Model.php b/src/Attribute/Model.php similarity index 97% rename from src/Annotation/Model.php rename to src/Attribute/Model.php index cbc610fad..57aaee5e3 100644 --- a/src/Annotation/Model.php +++ b/src/Attribute/Model.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Nelmio\ApiDocBundle\Annotation; +namespace Nelmio\ApiDocBundle\Attribute; use OpenApi\Annotations\Parameter; use OpenApi\Attributes\Attachable; diff --git a/src/Annotation/Operation.php b/src/Attribute/Operation.php similarity index 89% rename from src/Annotation/Operation.php rename to src/Attribute/Operation.php index ed153e539..092458fa2 100644 --- a/src/Annotation/Operation.php +++ b/src/Attribute/Operation.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Nelmio\ApiDocBundle\Annotation; +namespace Nelmio\ApiDocBundle\Attribute; use OpenApi\Annotations\Operation as BaseOperation; diff --git a/src/Annotation/Security.php b/src/Attribute/Security.php similarity index 95% rename from src/Annotation/Security.php rename to src/Attribute/Security.php index f057282f4..839fd7e7e 100644 --- a/src/Annotation/Security.php +++ b/src/Attribute/Security.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Nelmio\ApiDocBundle\Annotation; +namespace Nelmio\ApiDocBundle\Attribute; use OpenApi\Annotations\AbstractAnnotation; diff --git a/src/Describer/OpenApiPhpDescriber.php b/src/Describer/OpenApiPhpDescriber.php index 79a807c72..bec30c519 100644 --- a/src/Describer/OpenApiPhpDescriber.php +++ b/src/Describer/OpenApiPhpDescriber.php @@ -11,8 +11,8 @@ namespace Nelmio\ApiDocBundle\Describer; -use Nelmio\ApiDocBundle\Annotation\Operation; -use Nelmio\ApiDocBundle\Annotation\Security; +use Nelmio\ApiDocBundle\Attribute\Operation; +use Nelmio\ApiDocBundle\Attribute\Security; use Nelmio\ApiDocBundle\OpenApiPhp\Util; use Nelmio\ApiDocBundle\Util\ControllerReflector; use Nelmio\ApiDocBundle\Util\SetsContextTrait; diff --git a/src/OpenApiPhp/ModelRegister.php b/src/OpenApiPhp/ModelRegister.php index de20ee6bb..7a70bb5fd 100644 --- a/src/OpenApiPhp/ModelRegister.php +++ b/src/OpenApiPhp/ModelRegister.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\OpenApiPhp; -use Nelmio\ApiDocBundle\Annotation\Model as ModelAnnotation; +use Nelmio\ApiDocBundle\Attribute\Model as ModelAnnotation; use Nelmio\ApiDocBundle\Model\Model; use Nelmio\ApiDocBundle\Model\ModelRegistry; use OpenApi\Analysis; diff --git a/src/Routing/FilteredRouteCollectionBuilder.php b/src/Routing/FilteredRouteCollectionBuilder.php index a896466c9..c6a32a17b 100644 --- a/src/Routing/FilteredRouteCollectionBuilder.php +++ b/src/Routing/FilteredRouteCollectionBuilder.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Routing; -use Nelmio\ApiDocBundle\Annotation\Areas; +use Nelmio\ApiDocBundle\Attribute\Areas; use Nelmio\ApiDocBundle\Util\ControllerReflector; use OpenApi\Annotations\AbstractAnnotation; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -153,7 +153,7 @@ private function defaultRouteDisabled(Route $route): bool }, $method->getAttributes(AbstractAnnotation::class, \ReflectionAttribute::IS_INSTANCEOF)); foreach ($annotations as $annotation) { - if (false !== strpos(get_class($annotation), 'Nelmio\\ApiDocBundle\\Annotation') + if (false !== strpos(get_class($annotation), 'Nelmio\\ApiDocBundle\\Attribute') || false !== strpos(get_class($annotation), 'OpenApi\\Annotations') || false !== strpos(get_class($annotation), 'OpenApi\\Attributes') ) { diff --git a/tests/Functional/Controller/ApiController.php b/tests/Functional/Controller/ApiController.php index 18d9e4775..a36d11382 100644 --- a/tests/Functional/Controller/ApiController.php +++ b/tests/Functional/Controller/ApiController.php @@ -11,10 +11,10 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Areas; -use Nelmio\ApiDocBundle\Annotation\Model; -use Nelmio\ApiDocBundle\Annotation\Operation; -use Nelmio\ApiDocBundle\Annotation\Security; +use Nelmio\ApiDocBundle\Attribute\Areas; +use Nelmio\ApiDocBundle\Attribute\Model; +use Nelmio\ApiDocBundle\Attribute\Operation; +use Nelmio\ApiDocBundle\Attribute\Security; use Nelmio\ApiDocBundle\Tests\Functional\Entity\ArrayItems\Dictionary; use Nelmio\ApiDocBundle\Tests\Functional\Entity\ArrayItems\Foo; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article; diff --git a/tests/Functional/Controller/BazingaController.php b/tests/Functional/Controller/BazingaController.php index f12aade51..726d4f7fb 100644 --- a/tests/Functional/Controller/BazingaController.php +++ b/tests/Functional/Controller/BazingaController.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use Nelmio\ApiDocBundle\Tests\Functional\Entity\BazingaUser; use OpenApi\Attributes as OA; use Symfony\Component\Routing\Annotation\Route; diff --git a/tests/Functional/Controller/BazingaTypedController.php b/tests/Functional/Controller/BazingaTypedController.php index a610fe634..04e652f45 100644 --- a/tests/Functional/Controller/BazingaTypedController.php +++ b/tests/Functional/Controller/BazingaTypedController.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use Nelmio\ApiDocBundle\Tests\Functional\EntityExcluded\BazingaUserTyped; use OpenApi\Attributes as OA; use Symfony\Component\Routing\Annotation\Route; diff --git a/tests/Functional/Controller/ClassApiController.php b/tests/Functional/Controller/ClassApiController.php index ac85ef9bc..fc2cf19ea 100644 --- a/tests/Functional/Controller/ClassApiController.php +++ b/tests/Functional/Controller/ClassApiController.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Security; +use Nelmio\ApiDocBundle\Attribute\Security; use OpenApi\Attributes as OAT; use Symfony\Component\Routing\Annotation\Route; diff --git a/tests/Functional/Controller/Controller2209.php b/tests/Functional/Controller/Controller2209.php index 7ea767869..dd22ad84e 100644 --- a/tests/Functional/Controller/Controller2209.php +++ b/tests/Functional/Controller/Controller2209.php @@ -13,7 +13,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article81; use OpenApi\Attributes as OA; use Symfony\Component\HttpFoundation\JsonResponse; diff --git a/tests/Functional/Controller/JMSController.php b/tests/Functional/Controller/JMSController.php index b01243a61..4124f708b 100644 --- a/tests/Functional/Controller/JMSController.php +++ b/tests/Functional/Controller/JMSController.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article81; use Nelmio\ApiDocBundle\Tests\Functional\Entity\DiscriminatorMap\JMSAbstractUser; use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSComplex; diff --git a/tests/Functional/Controller/JmsOptOutController.php b/tests/Functional/Controller/JmsOptOutController.php index a138e9748..997069fef 100644 --- a/tests/Functional/Controller/JmsOptOutController.php +++ b/tests/Functional/Controller/JmsOptOutController.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use Nelmio\ApiDocBundle\Tests\Functional\Entity\JMSUser; use OpenApi\Attributes as OA; use Symfony\Component\Routing\Annotation\Route; diff --git a/tests/Functional/Controller/MapRequestPayloadController.php b/tests/Functional/Controller/MapRequestPayloadController.php index 88921cb58..6d7f1047e 100644 --- a/tests/Functional/Controller/MapRequestPayloadController.php +++ b/tests/Functional/Controller/MapRequestPayloadController.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use Nelmio\ApiDocBundle\Tests\Functional\Entity\Article81; use Nelmio\ApiDocBundle\Tests\Functional\Entity\SymfonyConstraintsWithValidationGroups; use Symfony\Component\HttpKernel\Attribute\MapRequestPayload; diff --git a/tests/Functional/Controller/OperationIdController.php b/tests/Functional/Controller/OperationIdController.php index 45be34854..82b18704f 100644 --- a/tests/Functional/Controller/OperationIdController.php +++ b/tests/Functional/Controller/OperationIdController.php @@ -13,7 +13,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Security; +use Nelmio\ApiDocBundle\Attribute\Security; use OpenApi\Attributes as OA; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Annotation\Route; diff --git a/tests/Functional/Controller/PromotedPropertiesController81.php b/tests/Functional/Controller/PromotedPropertiesController81.php index b12e4669f..080da7fef 100644 --- a/tests/Functional/Controller/PromotedPropertiesController81.php +++ b/tests/Functional/Controller/PromotedPropertiesController81.php @@ -13,7 +13,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use Nelmio\ApiDocBundle\Tests\Functional\Entity\EntityWithPromotedPropertiesWithDefaults; use OpenApi\Attributes as OA; use Symfony\Component\Routing\Annotation\Route; diff --git a/tests/Functional/Entity/JMSComplex.php b/tests/Functional/Entity/JMSComplex.php index a7dd564b2..0fb475224 100644 --- a/tests/Functional/Entity/JMSComplex.php +++ b/tests/Functional/Entity/JMSComplex.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use JMS\Serializer\Annotation as Serializer; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use OpenApi\Attributes as OA; #[Serializer\ExclusionPolicy('all')] diff --git a/tests/Functional/Entity/JMSDualComplex.php b/tests/Functional/Entity/JMSDualComplex.php index 67cbefc03..ac1847d52 100644 --- a/tests/Functional/Entity/JMSDualComplex.php +++ b/tests/Functional/Entity/JMSDualComplex.php @@ -12,7 +12,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Entity; use JMS\Serializer\Annotation as Serializer; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use OpenApi\Attributes as OA; class JMSDualComplex diff --git a/tests/Functional/Form/FormWithModel.php b/tests/Functional/Form/FormWithModel.php index 925eb5ee2..329fc5f3a 100644 --- a/tests/Functional/Form/FormWithModel.php +++ b/tests/Functional/Form/FormWithModel.php @@ -11,7 +11,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Form; -use Nelmio\ApiDocBundle\Annotation\Model; +use Nelmio\ApiDocBundle\Attribute\Model; use Nelmio\ApiDocBundle\Tests\Functional\Entity\User; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; diff --git a/tests/RouteDescriber/RouteArgumentDescriber/SymfonyMapRequestPayloadDescriberTest.php b/tests/RouteDescriber/RouteArgumentDescriber/SymfonyMapRequestPayloadDescriberTest.php index 613a2ea18..eedbe7c06 100644 --- a/tests/RouteDescriber/RouteArgumentDescriber/SymfonyMapRequestPayloadDescriberTest.php +++ b/tests/RouteDescriber/RouteArgumentDescriber/SymfonyMapRequestPayloadDescriberTest.php @@ -13,7 +13,7 @@ namespace Nelmio\ApiDocBundle\Tests\RouteDescriber\RouteArgumentDescriber; -use Nelmio\ApiDocBundle\Annotation\Operation; +use Nelmio\ApiDocBundle\Attribute\Operation; use Nelmio\ApiDocBundle\Model\ModelRegistry; use Nelmio\ApiDocBundle\ModelDescriber\ModelDescriberInterface; use Nelmio\ApiDocBundle\RouteDescriber\RouteArgumentDescriber\SymfonyMapRequestPayloadDescriber; diff --git a/tests/Routing/FilteredRouteCollectionBuilderTest.php b/tests/Routing/FilteredRouteCollectionBuilderTest.php index 3bb1900cc..672c009e6 100644 --- a/tests/Routing/FilteredRouteCollectionBuilderTest.php +++ b/tests/Routing/FilteredRouteCollectionBuilderTest.php @@ -11,8 +11,8 @@ namespace Nelmio\ApiDocBundle\Tests\Routing; -use Nelmio\ApiDocBundle\Annotation\Areas; -use Nelmio\ApiDocBundle\Annotation\Operation; +use Nelmio\ApiDocBundle\Attribute\Areas; +use Nelmio\ApiDocBundle\Attribute\Operation; use Nelmio\ApiDocBundle\Routing\FilteredRouteCollectionBuilder; use Nelmio\ApiDocBundle\Util\ControllerReflector; use OpenApi\Attributes\Parameter; From 9a5662ec2f2c73000b45ec0629126ee08fb58e1f Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 13:19:01 +0200 Subject: [PATCH 02/11] rename with_annotation config option --- UPGRADE-5.0.md | 12 +++++++++++- src/DependencyInjection/Configuration.php | 8 ++++---- src/DependencyInjection/NelmioApiDocExtension.php | 2 +- src/Routing/FilteredRouteCollectionBuilder.php | 6 +++--- tests/DependencyInjection/ConfigurationTest.php | 8 ++++---- tests/Routing/FilteredRouteCollectionBuilderTest.php | 12 ++++++------ 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index abdcff0c7..642d662bd 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -26,4 +26,14 @@ This causes the following breaking changes in classes that used annotations: - BC BREAK: Removed 1st parameter `?Reader $annotationReader` from `Nelmio\ApiDocBundle\RouteDescriber\FosRestDescriber::__construct()` - BC BREAK: Removed 1st parameter `?Reader $annotationReader` from `Nelmio\ApiDocBundle\Routing\FilteredRouteCollectionBuilder::__construct()` -## BC BREAK: `Nelmio\ApiDocBundle\Annotation` namespace has been moved to `Nelmio\ApiDocBundle\Attribute` \ No newline at end of file +## BC BREAK: `Nelmio\ApiDocBundle\Annotation` namespace has been moved to `Nelmio\ApiDocBundle\Attribute` + +## BC BREAK: Configuration option `with_annotation` has been renamed to `with_attribute` +```diff +nelmio_api_doc: + areas: + path_patterns: + - ^/api/foo +- with_annotation: true ++ with_attribute: true +``` \ No newline at end of file diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 0b2ec84fb..60b9831bf 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -26,7 +26,7 @@ public function getConfigTreeBuilder(): TreeBuilder $rootNode ->children() ->booleanNode('use_validation_groups') - ->info('If true, `groups` passed to @Model annotations will be used to limit validation constraints') + ->info('If true, `groups` passed to #[Model] attributes will be used to limit validation constraints') ->defaultFalse() ->end() ->arrayNode('cache') @@ -86,7 +86,7 @@ public function getConfigTreeBuilder(): TreeBuilder 'default' => [ 'path_patterns' => [], 'host_patterns' => [], - 'with_annotation' => false, + 'with_attribute' => false, 'documentation' => [], 'name_patterns' => [], 'disable_default_routes' => false, @@ -127,9 +127,9 @@ public function getConfigTreeBuilder(): TreeBuilder ->example(['^api_v1']) ->prototype('scalar')->end() ->end() - ->booleanNode('with_annotation') + ->booleanNode('with_attribute') ->defaultFalse() - ->info('whether to filter by annotation') + ->info('whether to filter by attributes') ->end() ->booleanNode('disable_default_routes') ->defaultFalse() diff --git a/src/DependencyInjection/NelmioApiDocExtension.php b/src/DependencyInjection/NelmioApiDocExtension.php index 1995f2dc1..c699f6fa0 100644 --- a/src/DependencyInjection/NelmioApiDocExtension.php +++ b/src/DependencyInjection/NelmioApiDocExtension.php @@ -130,7 +130,7 @@ public function load(array $configs, ContainerBuilder $container): void if (0 === count($areaConfig['path_patterns']) && 0 === count($areaConfig['host_patterns']) && 0 === count($areaConfig['name_patterns']) - && false === $areaConfig['with_annotation'] + && false === $areaConfig['with_attribute'] && false === $areaConfig['disable_default_routes'] ) { $container->setDefinition(sprintf('nelmio_api_doc.routes.%s', $area), $routesDefinition) diff --git a/src/Routing/FilteredRouteCollectionBuilder.php b/src/Routing/FilteredRouteCollectionBuilder.php index c6a32a17b..02adde0f8 100644 --- a/src/Routing/FilteredRouteCollectionBuilder.php +++ b/src/Routing/FilteredRouteCollectionBuilder.php @@ -43,13 +43,13 @@ public function __construct( 'path_patterns' => [], 'host_patterns' => [], 'name_patterns' => [], - 'with_annotation' => false, + 'with_attribute' => false, 'disable_default_routes' => false, ]) ->setAllowedTypes('path_patterns', 'string[]') ->setAllowedTypes('host_patterns', 'string[]') ->setAllowedTypes('name_patterns', 'string[]') - ->setAllowedTypes('with_annotation', 'boolean') + ->setAllowedTypes('with_attribute', 'boolean') ->setAllowedTypes('disable_default_routes', 'boolean') ; @@ -117,7 +117,7 @@ private function matchName(string $name): bool private function matchAnnotation(Route $route): bool { - if (false === $this->options['with_annotation']) { + if (false === $this->options['with_attribute']) { return true; } diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index 0bca5e32c..9d0fe1f2f 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -38,7 +38,7 @@ public function testDefaultArea(): void 'path_patterns' => ['/foo'], 'host_patterns' => [], 'name_patterns' => [], - 'with_annotation' => false, + 'with_attribute' => false, 'disable_default_routes' => false, 'documentation' => [], ], @@ -53,7 +53,7 @@ public function testAreas(): void 'default' => [ 'path_patterns' => ['/foo'], 'host_patterns' => [], - 'with_annotation' => false, + 'with_attribute' => false, 'documentation' => [], 'name_patterns' => [], 'disable_default_routes' => false, @@ -61,7 +61,7 @@ public function testAreas(): void 'internal' => [ 'path_patterns' => ['/internal'], 'host_patterns' => ['^swagger\.'], - 'with_annotation' => false, + 'with_attribute' => false, 'documentation' => [], 'name_patterns' => [], 'disable_default_routes' => false, @@ -69,7 +69,7 @@ public function testAreas(): void 'commercial' => [ 'path_patterns' => ['/internal'], 'host_patterns' => [], - 'with_annotation' => false, + 'with_attribute' => false, 'documentation' => [], 'name_patterns' => [], 'disable_default_routes' => false, diff --git a/tests/Routing/FilteredRouteCollectionBuilderTest.php b/tests/Routing/FilteredRouteCollectionBuilderTest.php index 672c009e6..6fd199baa 100644 --- a/tests/Routing/FilteredRouteCollectionBuilderTest.php +++ b/tests/Routing/FilteredRouteCollectionBuilderTest.php @@ -108,7 +108,7 @@ public static function getInvalidOptions(): \Generator yield [['path_patterns' => [null]]]; yield [['path_patterns' => [new \stdClass()]]]; yield [['path_patterns' => ['^/foo$', 1]]]; - yield [['with_annotation' => ['an array']]]; + yield [['with_attribute' => ['an array']]]; yield [['path_patterns' => 'a string']]; yield [['path_patterns' => 11]]; yield [['name_patterns' => 22]]; @@ -209,13 +209,13 @@ public function fooAction(): void 'r10', new Route('/api/areas_attributes/new', ['_controller' => 'ApiController::newAreaActionAttributes']), new \ReflectionMethod($apiController, 'fooAction'), - ['with_annotation' => true], + ['with_attribute' => true], ], 'with attribute and path patterns' => [ 'r10', new Route('/api/areas_attributes/new', ['_controller' => 'ApiController::newAreaActionAttributes']), new \ReflectionMethod($apiController, 'fooAction'), - ['path_patterns' => ['^/api'], 'with_annotation' => true], + ['path_patterns' => ['^/api'], 'with_attribute' => true], ], ]; @@ -229,7 +229,7 @@ public function fooAction(): void 'r10', new Route('/api/areas_attributes/new', ['_controller' => 'ApiController::newAreaActionAttributes']), new \ReflectionMethod($apiController, 'fooAction'), - ['with_annotation' => true], + ['with_attribute' => true], ]; } @@ -310,7 +310,7 @@ public function fooAction(): void 'r10', new Route('/api/foo', ['_controller' => 'ApiController::fooAction']), new \ReflectionMethod($apiController, 'fooAction'), - ['with_annotation' => true], + ['with_attribute' => true], 0, ]; @@ -387,7 +387,7 @@ public function testRoutesWithInvalidController(): void $routeBuilder = new FilteredRouteCollectionBuilder( $controllerReflectorStub, 'area', - ['with_annotation' => true], + ['with_attribute' => true], ); $filteredRoutes = $routeBuilder->filter($routes); From 8169b06d42b86323f7bd78f018a0f362f5107a85 Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 13:53:44 +0200 Subject: [PATCH 03/11] cleanup mentions of annotations --- src/ApiDocGenerator.php | 4 +- src/DependencyInjection/Configuration.php | 2 +- .../UndocumentedArrayItemsException.php | 2 +- .../Annotations/OpenApiAnnotationsReader.php | 12 +-- .../SymfonyConstraintAnnotationReader.php | 98 +++++++++---------- src/ModelDescriber/FormModelDescriber.php | 2 +- src/ModelDescriber/JMSModelDescriber.php | 2 +- src/ModelDescriber/ObjectModelDescriber.php | 4 +- src/OpenApiPhp/ModelRegister.php | 14 +-- src/RouteDescriber/FosRestDescriber.php | 52 +++++----- 10 files changed, 96 insertions(+), 96 deletions(-) diff --git a/src/ApiDocGenerator.php b/src/ApiDocGenerator.php index cedcd1614..e22c36106 100644 --- a/src/ApiDocGenerator.php +++ b/src/ApiDocGenerator.php @@ -123,7 +123,7 @@ public function generate(): OpenApi $analysis = new Analysis([], $context); $analysis->addAnnotation($this->openApi, $context); - // Register model annotations + // Register model attributes $modelRegister = new ModelRegister($modelRegistry, $this->mediaTypes); $modelRegister($analysis); @@ -152,7 +152,7 @@ private function getProcessors(Generator $generator): array // Get the standard processors from the generator. $processors = $generator->getProcessors(); - // Remove OperationId processor as we use a lot of generated annotations which do not have enough information in their context + // Remove OperationId processor as we use a lot of generated attributes which do not have enough information in their context // to generate these ids properly. // @see \Nelmio\ApiDocBundle\OpenApiPhp\Util::createContext foreach ($processors as $key => $processor) { diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 60b9831bf..790f24587 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -133,7 +133,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->booleanNode('disable_default_routes') ->defaultFalse() - ->info('if set disables default routes without annotations') + ->info('if set disables default routes without attributes') ->end() ->arrayNode('documentation') ->useAttributeAsKey('key') diff --git a/src/Exception/UndocumentedArrayItemsException.php b/src/Exception/UndocumentedArrayItemsException.php index 2b2e812b5..f6cee4224 100644 --- a/src/Exception/UndocumentedArrayItemsException.php +++ b/src/Exception/UndocumentedArrayItemsException.php @@ -37,7 +37,7 @@ public function __construct(?string $class = null, string $path = '') } $propertyName .= $path; - parent::__construct(sprintf('Property "%s" is an array, but its items type isn\'t specified. You can specify that by using the type `string[]` for instance or `@OA\Property(type="array", @OA\Items(type="string"))`.', $propertyName)); + parent::__construct(sprintf('Property "%s" is an array, but its items type isn\'t specified. You can specify that by using the type `string[]` for instance or `#[OA\Property(type="array", new OA\Items(type="string"))]`.', $propertyName)); } /** diff --git a/src/ModelDescriber/Annotations/OpenApiAnnotationsReader.php b/src/ModelDescriber/Annotations/OpenApiAnnotationsReader.php index 8debfc04d..c61b0f201 100644 --- a/src/ModelDescriber/Annotations/OpenApiAnnotationsReader.php +++ b/src/ModelDescriber/Annotations/OpenApiAnnotationsReader.php @@ -39,11 +39,11 @@ public function __construct(ModelRegistry $modelRegistry, array $mediaTypes) public function updateSchema(\ReflectionClass $reflectionClass, OA\Schema $schema): void { - if (null === $oaSchema = $this->getAnnotation($schema->_context, $reflectionClass, OA\Schema::class)) { + if (null === $oaSchema = $this->getAttribute($schema->_context, $reflectionClass, OA\Schema::class)) { return; } - // Read @Model annotations + // Read #[Model] attributes $this->modelRegister->__invoke(new Analysis([$oaSchema], Util::createContext())); if (!$oaSchema->validate()) { @@ -58,7 +58,7 @@ public function updateSchema(\ReflectionClass $reflectionClass, OA\Schema $schem */ public function getPropertyName($reflection, string $default): string { - if (null === $oaProperty = $this->getAnnotation(new Context(), $reflection, OA\Property::class)) { + if (null === $oaProperty = $this->getAttribute(new Context(), $reflection, OA\Property::class)) { return $default; } @@ -71,11 +71,11 @@ public function getPropertyName($reflection, string $default): string */ public function updateProperty($reflection, OA\Property $property, ?array $serializationGroups = null): void { - if (null === $oaProperty = $this->getAnnotation($property->_context, $reflection, OA\Property::class)) { + if (null === $oaProperty = $this->getAttribute($property->_context, $reflection, OA\Property::class)) { return; } - // Read @Model annotations + // Read #[Model] attributes $this->modelRegister->__invoke(new Analysis([$oaProperty], Util::createContext()), $serializationGroups); if (!$oaProperty->validate()) { @@ -93,7 +93,7 @@ public function updateProperty($reflection, OA\Property $property, ?array $seria * * @return T|null */ - private function getAnnotation(Context $parentContext, $reflection, string $className) + private function getAttribute(Context $parentContext, $reflection, string $className) { $this->setContextFromReflection($parentContext, $reflection); diff --git a/src/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php b/src/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php index d6b88df39..1861ff90a 100644 --- a/src/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php +++ b/src/ModelDescriber/Annotations/SymfonyConstraintAnnotationReader.php @@ -46,24 +46,24 @@ public function __construct(bool $useValidationGroups = false) */ public function updateProperty($reflection, OA\Property $property, ?array $validationGroups = null): void { - foreach ($this->getAnnotations($property->_context, $reflection, $validationGroups) as $outerAnnotation) { - $innerAnnotations = $outerAnnotation instanceof Assert\Compound || $outerAnnotation instanceof Assert\Sequentially - ? $outerAnnotation->constraints - : [$outerAnnotation]; + foreach ($this->getAttributes($property->_context, $reflection, $validationGroups) as $outerAttribute) { + $innerAttributes = $outerAttribute instanceof Assert\Compound || $outerAttribute instanceof Assert\Sequentially + ? $outerAttribute->constraints + : [$outerAttribute]; - $this->processPropertyAnnotations($reflection, $property, $innerAnnotations); + $this->processPropertyAttributes($reflection, $property, $innerAttributes); } } /** * @param \ReflectionProperty|\ReflectionMethod $reflection - * @param Constraint[] $annotations + * @param Constraint[] $attributes */ - private function processPropertyAnnotations($reflection, OA\Property $property, array $annotations): void + private function processPropertyAttributes($reflection, OA\Property $property, array $attributes): void { - foreach ($annotations as $annotation) { - if ($annotation instanceof Assert\NotBlank || $annotation instanceof Assert\NotNull) { - if ($annotation instanceof Assert\NotBlank && $annotation->allowNull) { + foreach ($attributes as $attribute) { + if ($attribute instanceof Assert\NotBlank || $attribute instanceof Assert\NotNull) { + if ($attribute instanceof Assert\NotBlank && $attribute->allowNull) { // The field is optional return; } @@ -87,48 +87,48 @@ private function processPropertyAnnotations($reflection, OA\Property $property, $this->schema->required = array_values(array_unique($existingRequiredFields)); $property->nullable = false; - } elseif ($annotation instanceof Assert\Length) { - if (isset($annotation->min)) { - $property->minLength = $annotation->min; + } elseif ($attribute instanceof Assert\Length) { + if (isset($attribute->min)) { + $property->minLength = $attribute->min; } - if (isset($annotation->max)) { - $property->maxLength = $annotation->max; + if (isset($attribute->max)) { + $property->maxLength = $attribute->max; } - } elseif ($annotation instanceof Assert\Regex) { - $this->appendPattern($property, $annotation->getHtmlPattern()); - } elseif ($annotation instanceof Assert\Count) { - if (isset($annotation->min)) { - $property->minItems = $annotation->min; + } elseif ($attribute instanceof Assert\Regex) { + $this->appendPattern($property, $attribute->getHtmlPattern()); + } elseif ($attribute instanceof Assert\Count) { + if (isset($attribute->min)) { + $property->minItems = $attribute->min; } - if (isset($annotation->max)) { - $property->maxItems = $annotation->max; + if (isset($attribute->max)) { + $property->maxItems = $attribute->max; } - } elseif ($annotation instanceof Assert\Choice) { - $this->applyEnumFromChoiceConstraint($property, $annotation, $reflection); - } elseif ($annotation instanceof Assert\Range) { - if (\is_int($annotation->min)) { - $property->minimum = $annotation->min; + } elseif ($attribute instanceof Assert\Choice) { + $this->applyEnumFromChoiceConstraint($property, $attribute, $reflection); + } elseif ($attribute instanceof Assert\Range) { + if (\is_int($attribute->min)) { + $property->minimum = $attribute->min; } - if (\is_int($annotation->max)) { - $property->maximum = $annotation->max; + if (\is_int($attribute->max)) { + $property->maximum = $attribute->max; } - } elseif ($annotation instanceof Assert\LessThan) { - if (\is_int($annotation->value)) { + } elseif ($attribute instanceof Assert\LessThan) { + if (\is_int($attribute->value)) { $property->exclusiveMaximum = true; - $property->maximum = $annotation->value; + $property->maximum = $attribute->value; } - } elseif ($annotation instanceof Assert\LessThanOrEqual) { - if (\is_int($annotation->value)) { - $property->maximum = $annotation->value; + } elseif ($attribute instanceof Assert\LessThanOrEqual) { + if (\is_int($attribute->value)) { + $property->maximum = $attribute->value; } - } elseif ($annotation instanceof Assert\GreaterThan) { - if (\is_int($annotation->value)) { + } elseif ($attribute instanceof Assert\GreaterThan) { + if (\is_int($attribute->value)) { $property->exclusiveMinimum = true; - $property->minimum = $annotation->value; + $property->minimum = $attribute->value; } - } elseif ($annotation instanceof Assert\GreaterThanOrEqual) { - if (\is_int($annotation->value)) { - $property->minimum = $annotation->value; + } elseif ($attribute instanceof Assert\GreaterThanOrEqual) { + if (\is_int($attribute->value)) { + $property->minimum = $attribute->value; } } } @@ -179,14 +179,14 @@ private function applyEnumFromChoiceConstraint(OA\Schema $property, Assert\Choic * * @return iterable */ - private function getAnnotations(Context $parentContext, $reflection, ?array $validationGroups): iterable + private function getAttributes(Context $parentContext, $reflection, ?array $validationGroups): iterable { - // To correctly load OA annotations + // To correctly load OA attributes $this->setContextFromReflection($parentContext, $reflection); - foreach ($this->locateAnnotations($reflection) as $annotation) { - if (!$this->useValidationGroups || $this->isConstraintInGroup($annotation, $validationGroups)) { - yield $annotation; + foreach ($this->locateAttributes($reflection) as $attribute) { + if (!$this->useValidationGroups || $this->isConstraintInGroup($attribute, $validationGroups)) { + yield $attribute; } } @@ -198,7 +198,7 @@ private function getAnnotations(Context $parentContext, $reflection, ?array $val * * @return \Traversable */ - private function locateAnnotations($reflection): \Traversable + private function locateAttributes($reflection): \Traversable { if (class_exists(Constraint::class)) { foreach ($reflection->getAttributes(Constraint::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { @@ -217,7 +217,7 @@ private function locateAnnotations($reflection): \Traversable * * @param string[]|null $validationGroups */ - private function isConstraintInGroup(Constraint $annotation, ?array $validationGroups): bool + private function isConstraintInGroup(Constraint $attribute, ?array $validationGroups): bool { if (null === $validationGroups) { $validationGroups = [Constraint::DEFAULT_GROUP]; @@ -225,7 +225,7 @@ private function isConstraintInGroup(Constraint $annotation, ?array $validationG return [] !== array_intersect( $validationGroups, - (array) $annotation->groups + (array) $attribute->groups ); } } diff --git a/src/ModelDescriber/FormModelDescriber.php b/src/ModelDescriber/FormModelDescriber.php index bd6e7f5a3..ee4a24398 100644 --- a/src/ModelDescriber/FormModelDescriber.php +++ b/src/ModelDescriber/FormModelDescriber.php @@ -122,7 +122,7 @@ private function parseForm(OA\Schema $schema, FormInterface $form): void if ($config->hasOption('documentation')) { $property->mergeProperties($config->getOption('documentation')); - // Parse inner @Model annotations + // Parse inner #[Model] attributes $modelRegister = new ModelRegister($this->modelRegistry, $this->mediaTypes); $modelRegister->__invoke(new Analysis([$property], Util::createContext())); } diff --git a/src/ModelDescriber/JMSModelDescriber.php b/src/ModelDescriber/JMSModelDescriber.php index f5497efa7..ca17b5a00 100644 --- a/src/ModelDescriber/JMSModelDescriber.php +++ b/src/ModelDescriber/JMSModelDescriber.php @@ -131,7 +131,7 @@ public function describe(Model $model, OA\Schema $schema) $context->pushPropertyMetadata($item); $name = true === $isJmsV1 ? $this->namingStrategy->translateName($item) : $item->serializedName; - // read property options from Swagger Property annotation if it exists + // read property options from Swagger Property attribute if it exists $reflections = []; if (true === $isJmsV1 && property_exists($item, 'reflection') && null !== $item->reflection) { diff --git a/src/ModelDescriber/ObjectModelDescriber.php b/src/ModelDescriber/ObjectModelDescriber.php index 0ff4effdd..b7b124074 100644 --- a/src/ModelDescriber/ObjectModelDescriber.php +++ b/src/ModelDescriber/ObjectModelDescriber.php @@ -172,7 +172,7 @@ public function describe(Model $model, OA\Schema $schema) $types = $this->propertyInfo->getTypes($class, $propertyName); if (null === $types || 0 === count($types)) { - throw new \LogicException(sprintf('The PropertyInfo component was not able to guess the type of %s::$%s. You may need to add a `@var` annotation or use `@OA\Property(type="")` to make its type explicit.', $class, $propertyName)); + throw new \LogicException(sprintf('The PropertyInfo component was not able to guess the type of %s::$%s. You may need to add a `@var` annotation or use `#[OA\Property(type="")]` to make its type explicit.', $class, $propertyName)); } $this->describeProperty($types, $model, $property, $propertyName, $schema); @@ -227,7 +227,7 @@ private function describeProperty(array $types, Model $model, OA\Schema $propert } } - throw new \Exception(sprintf('Type "%s" is not supported in %s::$%s. You may use the `@OA\Property(type="")` annotation to specify it manually.', $types[0]->getBuiltinType(), $model->getType()->getClassName(), $propertyName)); + throw new \Exception(sprintf('Type "%s" is not supported in %s::$%s. You may use the `#[OA\Property(type="")]` annotation to specify it manually.', $types[0]->getBuiltinType(), $model->getType()->getClassName(), $propertyName)); } /** diff --git a/src/OpenApiPhp/ModelRegister.php b/src/OpenApiPhp/ModelRegister.php index 7a70bb5fd..17d127057 100644 --- a/src/OpenApiPhp/ModelRegister.php +++ b/src/OpenApiPhp/ModelRegister.php @@ -46,7 +46,7 @@ public function __construct(ModelRegistry $modelRegistry, array $mediaTypes) public function __invoke(Analysis $analysis, ?array $parentGroups = null): void { foreach ($analysis->annotations as $annotation) { - // @Model using the ref field + // #[Model] using the ref field if ($annotation instanceof OA\Schema && $annotation->ref instanceof ModelAnnotation) { $model = $annotation->ref; @@ -60,15 +60,15 @@ public function __invoke(Analysis $analysis, ?array $parentGroups = null): void // Misusage of ::$ref if (($annotation instanceof OA\Response || $annotation instanceof OA\RequestBody) && $annotation->ref instanceof ModelAnnotation) { - throw new \InvalidArgumentException(sprintf('Using @Model inside @%s::$ref is not allowed. You should use ::$ref with @Property, @Parameter, @Schema, @Items but within @Response or @RequestBody you should put @Model directly at the root of the annotation : `@Response(..., @Model(...))`.', get_class($annotation))); + throw new \InvalidArgumentException(sprintf('Using #[Model] inside #[%s::$ref] is not allowed. You should use ::$ref with #[Property], #[Parameter], #[Schema], #[Items] but within #[Response] or #[RequestBody} You should use ::$content : `#[Response(..., content: new Model())]`.', get_class($annotation))); } // Implicit usages - // We don't use $ref for @Responses, @RequestBody and @Parameter to respect semantics - // We don't replace these objects with the @Model found (we inject it in a subfield) whereas we do for @Schemas + // We don't use $ref for #[Responses], #[RequestBody] and #[Parameter] to respect semantics + // We don't replace these objects with the #[Model] found (we inject it in a subfield) whereas we do for @Schemas - $model = $this->getModel($annotation); // We check whether there is a @Model annotation nested + $model = $this->getModel($annotation); // We check whether there is a #[Model] attribute nested if (null === $model) { continue; } @@ -88,7 +88,7 @@ public function __invoke(Analysis $analysis, ?array $parentGroups = null): void } if (!$annotation instanceof OA\Parameter) { - throw new \InvalidArgumentException(sprintf("@Model annotation can't be nested with an annotation of type @%s.", get_class($annotation))); + throw new \InvalidArgumentException(sprintf("#[Model] attribute can't be nested with an attribute of type @%s.", get_class($annotation))); } if ($annotation->schema instanceof OA\Schema && 'array' === $annotation->schema->type) { @@ -176,7 +176,7 @@ private function createContentForMediaType( break; default: - throw new \InvalidArgumentException(sprintf("@Model annotation is not compatible with the media types '%s'. It must be one of 'json' or 'xml'.", implode(',', $this->mediaTypes))); + throw new \InvalidArgumentException(sprintf("#[Model] attribute is not compatible with the media types '%s'. It must be one of 'json' or 'xml'.", implode(',', $this->mediaTypes))); } $annotation->merge([$modelAnnotation]); diff --git a/src/RouteDescriber/FosRestDescriber.php b/src/RouteDescriber/FosRestDescriber.php index 02655cc03..ee7ddbcd6 100644 --- a/src/RouteDescriber/FosRestDescriber.php +++ b/src/RouteDescriber/FosRestDescriber.php @@ -40,30 +40,30 @@ public function __construct(array $mediaTypes) public function describe(OA\OpenApi $api, Route $route, \ReflectionMethod $reflectionMethod): void { - $annotations = $this->getAttributesAsAnnotation($reflectionMethod, RequestParam::class); - $annotations = array_merge($annotations, $this->getAttributesAsAnnotation($reflectionMethod, QueryParam::class)); + $attributes = $this->getAttributes($reflectionMethod, RequestParam::class); + $attributes = array_merge($attributes, $this->getAttributes($reflectionMethod, QueryParam::class)); foreach ($this->getOperations($api, $route) as $operation) { - foreach ($annotations as $annotation) { - $parameterName = $annotation->key ?? $annotation->getName(); // the key used by fosrest + foreach ($attributes as $attribute) { + $parameterName = $attribute->key ?? $attribute->getName(); // the key used by fosrest - if ($annotation instanceof QueryParam) { - $name = $parameterName.($annotation->map ? '[]' : ''); + if ($attribute instanceof QueryParam) { + $name = $parameterName.($attribute->map ? '[]' : ''); $parameter = Util::getOperationParameter($operation, $name, 'query'); - $parameter->allowEmptyValue = $annotation->nullable && $annotation->allowBlank; + $parameter->allowEmptyValue = $attribute->nullable && $attribute->allowBlank; - $parameter->required = !$annotation->nullable && $annotation->strict; + $parameter->required = !$attribute->nullable && $attribute->strict; if (Generator::UNDEFINED === $parameter->description) { - $parameter->description = $annotation->description; + $parameter->description = $attribute->description; } - if ($annotation->map) { + if ($attribute->map) { $parameter->explode = true; } $schema = Util::getChild($parameter, OA\Schema::class); - $this->describeCommonSchemaFromAnnotation($schema, $annotation, $reflectionMethod); + $this->describeCommonSchemaFromAttribute($schema, $attribute, $reflectionMethod); } else { /** @var OA\RequestBody $requestBody */ $requestBody = Util::getChild($operation, OA\RequestBody::class); @@ -71,13 +71,13 @@ public function describe(OA\OpenApi $api, Route $route, \ReflectionMethod $refle $contentSchema = $this->getContentSchemaForType($requestBody, $mediaType); $schema = Util::getProperty($contentSchema, $parameterName); - if (!$annotation->nullable && $annotation->strict) { + if (!$attribute->nullable && $attribute->strict) { $requiredParameters = is_array($contentSchema->required) ? $contentSchema->required : []; $requiredParameters[] = $parameterName; $contentSchema->required = array_values(array_unique($requiredParameters)); } - $this->describeCommonSchemaFromAnnotation($schema, $annotation, $reflectionMethod); + $this->describeCommonSchemaFromAttribute($schema, $attribute, $reflectionMethod); } } } @@ -192,33 +192,33 @@ private function getContentSchemaForType(OA\RequestBody $requestBody, string $ty ); } - private function describeCommonSchemaFromAnnotation(OA\Schema $schema, AbstractScalarParam $annotation, \ReflectionMethod $reflectionMethod): void + private function describeCommonSchemaFromAttribute(OA\Schema $schema, AbstractScalarParam $attribute, \ReflectionMethod $reflectionMethod): void { - $schema->default = $annotation->getDefault(); + $schema->default = $attribute->getDefault(); if (Generator::UNDEFINED === $schema->type) { - $schema->type = $annotation->map ? 'array' : 'string'; + $schema->type = $attribute->map ? 'array' : 'string'; } - if ($annotation->map) { + if ($attribute->map) { $schema->type = 'array'; $schema->items = Util::getChild($schema, OA\Items::class); } - $pattern = $this->getPattern($annotation->requirements); + $pattern = $this->getPattern($attribute->requirements); if (null !== $pattern) { $schema->pattern = $pattern; } - $format = $this->getFormat($annotation->requirements); + $format = $this->getFormat($attribute->requirements); if (null !== $format) { $schema->format = $format; } - $enum = $this->getEnum($annotation->requirements, $reflectionMethod); + $enum = $this->getEnum($attribute->requirements, $reflectionMethod); if (null !== $enum) { - if ($annotation->requirements instanceof Choice) { - if ($annotation->requirements->multiple) { + if ($attribute->requirements instanceof Choice) { + if ($attribute->requirements->multiple) { $schema->type = 'array'; $schema->items = Util::createChild($schema, OA\Items::class, ['type' => 'string', 'enum' => $enum]); } else { @@ -235,13 +235,13 @@ private function describeCommonSchemaFromAnnotation(OA\Schema $schema, AbstractS * * @return T[] */ - private function getAttributesAsAnnotation(\ReflectionMethod $reflection, string $className): array + private function getAttributes(\ReflectionMethod $reflection, string $className): array { - $annotations = []; + $attributes = []; foreach ($reflection->getAttributes($className, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { - $annotations[] = $attribute->newInstance(); + $attributes[] = $attribute->newInstance(); } - return $annotations; + return $attributes; } } From f82395296fcf3b6d189e2e61c470b1467e2852c4 Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 15:15:49 +0200 Subject: [PATCH 04/11] add changelog --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f1a002d3..70dc95021 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # CHANGELOG +## 4.32.3 + +* Deprecated `Nelmio\ApiDocBundle\Annotation` namespace in favor of `Nelmio\ApiDocBundle\Attribute` namespace in preparation for 5.x. Consider upgrading to the new attribute syntax. +```diff +- use Nelmio\ApiDocBundle\Annotation\Areas; +- use Nelmio\ApiDocBundle\Annotation\Model; +- use Nelmio\ApiDocBundle\Annotation\Operation; +- use Nelmio\ApiDocBundle\Annotation\Security; + ++ use Nelmio\ApiDocBundle\Attribute\Areas; ++ use Nelmio\ApiDocBundle\Attribute\Model; ++ use Nelmio\ApiDocBundle\Attribute\Operation; ++ use Nelmio\ApiDocBundle\Attribute\Security; +``` + + ## 4.32.0 * Added support to configure `options` and `serializationContext` via `nelmio_api_doc.models.names`. From 055ee2ff0217b05ab117b9fd36996c5068f9afff Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 15:30:50 +0200 Subject: [PATCH 05/11] update docs --- docs/faq.rst | 33 +++++++++++++++++++++++++++++---- docs/index.rst | 10 +++++----- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index f3558634c..e126d14c1 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -182,7 +182,7 @@ Q: Areas feature doesn't fit my needs. So how can I group similar endpoints of o A: Use ``@OA\Tag`` annotation. -.. code-block:: php +.. code-block:: php-annotations /** * Class BookmarkController @@ -194,6 +194,18 @@ A: Use ``@OA\Tag`` annotation. // ... } +.. code-block:: php-attributes + + /** + * Class BookmarkController + */ + #[OA\Tag(name: "Bookmarks")] + class BookmarkController extends AbstractFOSRestController implements ContextPresetInterface + { + // ... + } + + Disable Default Section ----------------------- @@ -217,11 +229,10 @@ do I do that? A: By using the ``@OA\Schema`` annotation or attribute with a ``type`` or ``ref``. Note, however, that a ``type="object"`` will still read all a models properties. -.. code-block:: php +.. code-block:: php-annotations - Date: Fri, 25 Oct 2024 16:03:57 +0200 Subject: [PATCH 06/11] update docs to include attribute examples --- docs/alternative_names.rst | 30 +++++++---- docs/areas.rst | 53 ++++++++++++++----- docs/faq.rst | 106 +++++++++++++++++++------------------ docs/index.rst | 26 ++++----- docs/security.rst | 4 +- 5 files changed, 130 insertions(+), 89 deletions(-) diff --git a/docs/alternative_names.rst b/docs/alternative_names.rst index 6e1f4903d..90b1f7cd8 100644 --- a/docs/alternative_names.rst +++ b/docs/alternative_names.rst @@ -29,7 +29,7 @@ In this case the class ``App\Entity\User`` will be aliased into: .. tip:: - This allows to use normal references instead of ``@Model``. Notably, you can specify + This allows to use normal references instead of ``#[Model]``. Notably, you can specify the groups used for a model once in config and then refer to its alternative name: .. code-block:: yaml @@ -38,14 +38,26 @@ In this case the class ``App\Entity\User`` will be aliased into: models: names: [ { alias: MyModel, type: App\MyModel, groups: [light] }] - .. code-block:: php + .. configuration-block:: - class HomeController - { - /** - * @OA\Response(response=200, @OA\JsonContent(ref="#/components/schemas/MyModel")) - */ - public function indexAction() + .. code-block:: php-annotations + + class HomeController { + /** + * @OA\Response(response=200, @OA\JsonContent(ref="#/components/schemas/MyModel")) + */ + public function indexAction() + { + } } - } + + .. code-block:: php-attributes + + class HomeController + { + #[OA\Response(response: 200, content: new OA\JsonContent(ref: "#/components/schemas/MyModel"))] + public function indexAction() + { + } + } \ No newline at end of file diff --git a/docs/areas.rst b/docs/areas.rst index fa2705c8f..62511e4f9 100644 --- a/docs/areas.rst +++ b/docs/areas.rst @@ -62,12 +62,12 @@ Then update your routing to be able to access your different documentations: That's all! You can now access ``/api/doc/internal``, ``/api/doc/commercial`` and ``/api/doc/store``. -Use annotations to filter documented routes in each area +Use attributes to filter documented routes in each area -------------------------------------------------------- -You can use the `@Areas` annotation inside your controllers to define your routes' areas. +You can use the ``#[Areas]`` attribute inside your controllers to define your routes' areas. -First, you need to define which areas will use the`@Areas` annotations to filter +First, you need to define which areas will use the`#[Areas]` attributes to filter the routes that should be documented: .. code-block:: yaml @@ -79,20 +79,45 @@ the routes that should be documented: internal: with_annotation: true -Then add the annotation before your controller or action:: +Then add the attribute/annotation before your controller or action:: - use Nelmio\Annotations as Nelmio; +.. configuration-block:: + + .. code-block:: php-annotations + + use Nelmio\Annotation as Nelmio; + + /** + * @Nelmio\Areas({"internal"}) => All actions in this controller are documented under the 'internal' area + */ + class MyController + { + /** + * @Nelmio\Areas({"internal"}) => This action is documented under the 'internal' area + */ + public function index() + { + ... + } + } + + .. code-block:: php-attributes + + use Nelmio\Attribute as Nelmio; - /** - * @Nelmio\Areas({"internal"}) => All actions in this controller are documented under the 'internal' area - */ - class MyController - { /** - * @Nelmio\Areas({"internal"}) => This action is documented under the 'internal' area + * All actions in this controller are documented under the 'internal' area */ - public function index() + #[Nelmio\Areas(["internal"])] + class MyController { - ... + /** + * This action is documented under the 'internal' area + */ + #[Nelmio\Areas(["internal"])] + public function index() + { + ... + } } - } + diff --git a/docs/faq.rst b/docs/faq.rst index e126d14c1..496eb03be 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -180,30 +180,32 @@ Endpoints grouping Q: Areas feature doesn't fit my needs. So how can I group similar endpoints of one or more controllers in a separate section in the documentation? -A: Use ``@OA\Tag`` annotation. +A: Use ``#[OA\Tag]`` attribute. -.. code-block:: php-annotations +.. configuration-block:: - /** - * Class BookmarkController - * - * @OA\Tag(name="Bookmarks") - */ - class BookmarkController extends AbstractFOSRestController implements ContextPresetInterface - { - // ... - } + .. code-block:: php-annotations -.. code-block:: php-attributes + /** + * Class BookmarkController + * + * @OA\Tag(name="Bookmarks") + */ + class BookmarkController extends AbstractFOSRestController implements ContextPresetInterface + { + // ... + } - /** - * Class BookmarkController - */ - #[OA\Tag(name: "Bookmarks")] - class BookmarkController extends AbstractFOSRestController implements ContextPresetInterface - { - // ... - } + .. code-block:: php-attributes + + /** + * Class BookmarkController + */ + #[OA\Tag(name: "Bookmarks")] + class BookmarkController extends AbstractFOSRestController implements ContextPresetInterface + { + // ... + } Disable Default Section @@ -226,36 +228,38 @@ Overriding a Form or Plain PHP Object Schema Type Q: I'd like to define a PHP object or form with a type other any ``object``, how do I do that? -A: By using the ``@OA\Schema`` annotation or attribute with a ``type`` or ``ref``. +A: By using the ``#[OA\Schema]`` attribute/annotation with a ``type`` or ``ref``. Note, however, that a ``type="object"`` will still read all a models properties. -.. code-block:: php-annotations - - use Nelmio\ApiDocBundle\Annotation\Model; - use OpenApi\Annotations as OA; - - /** - * @OA\Schema(type="array", @OA\Items(ref=@Model(type=SomeEntity::class))) - * - * or define a `ref`: - * @OA\Schema(ref="#/components/schemas/SomeRef") - */ - class SomeCollection implements \IteratorAggregate - { - // ... - } - -.. code-block:: php-attributes - - use Nelmio\ApiDocBundle\Attribute\Model; - use OpenApi\Attributes as OA; - - /** - * or define a `ref`: - * #[OA\Schema(ref: "#/components/schemas/SomeRef") - */ - #[OA\Schema(type: "array", items: new OA\Items(ref: new Model(type: SomeEntity::class)))] - class SomeCollection implements \IteratorAggregate - { - // ... - } \ No newline at end of file +.. configuration-block:: + + .. code-block:: php-annotations + + use Nelmio\ApiDocBundle\Annotation\Model; + use OpenApi\Annotations as OA; + + /** + * @OA\Schema(type="array", @OA\Items(ref=@Model(type=SomeEntity::class))) + * + * or define a `ref`: + * @OA\Schema(ref="#/components/schemas/SomeRef") + */ + class SomeCollection implements \IteratorAggregate + { + // ... + } + + .. code-block:: php-attributes + + use Nelmio\ApiDocBundle\Attribute\Model; + use OpenApi\Attributes as OA; + + /** + * or define a `ref`: + * #[OA\Schema(ref: "#/components/schemas/SomeRef") + */ + #[OA\Schema(type: "array", items: new OA\Items(ref: new Model(type: SomeEntity::class)))] + class SomeCollection implements \IteratorAggregate + { + // ... + } \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 48d36ebe6..76203f2a4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -105,7 +105,7 @@ How does this bundle work? -------------------------- It generates an OpenAPI documentation from your Symfony app thanks to -**Describers**. One extracts data from SwaggerPHP annotations, one from your +**Describers**. One extracts data from SwaggerPHP attributes/annotations, one from your routes, etc. If you configured the ``app.swagger_ui`` route above, you can browse your @@ -151,8 +151,8 @@ You can configure global information in the bundle configuration ``documentation This configuration field can more generally be used to store your documentation as yaml. You may find in the ``.yaml`` files from `SwaggerPHP examples`_. -To document your routes, you can use the SwaggerPHP annotations and the -``Nelmio\ApiDocBundle\Attribute\Model`` annotation in your controllers:: +To document your routes, you can use the SwaggerPHP attributes/annotations and the +``#[Model]`` attribute/annotation in your controllers:: .. configuration-block:: @@ -244,7 +244,7 @@ The normal PHPDoc block on the controller method is used for the summary and des .. tip:: - Examples of using the annotations can be found in `SwaggerPHP examples`_. + Examples of using the attributes/annotations can be found in `SwaggerPHP examples`_. However, unlike in those examples, when using this bundle you don't need to specify paths and you can easily document models as well as some other properties described below as they can be automatically be documented using the Symfony integration. @@ -257,14 +257,14 @@ The normal PHPDoc block on the controller method is used for the summary and des Use Models ---------- -As shown in the example above, the bundle provides the ``@Model`` annotation. +As shown in the example above, the bundle provides the ``#[Model]`` attribute. Use it instead of a definition reference and the bundle will deduce your model properties. .. note:: A model can be a Symfony form type, a Doctrine ORM entity or a general PHP object. -This annotation has two options: +This attribute has two options: * ``type`` to specify your model's type:: @@ -397,12 +397,12 @@ that property type to not be nullable, for example. .. tip:: - When used at the root of ``@OA\Response`` and ``@OA\Parameter``, ``@Model`` is automatically nested - in a ``@OA\Schema``. + When used at the root of ``#[OA\Response]`` and ``#[OA\Parameter]``, ``#[Model]`` is automatically nested + in a ``#[OA\Schema]``. The media type defaults to ``application/json``. - To use ``@Model`` directly within a ``@OA\Schema``, ``@OA\Items`` or ``@OA\Property``, you have to use the ``$ref`` field:: + To use ``#[Model]`` directly within a ``#[OA\Schema]``, ``#[OA\Items]`` or ``#[OA\Property]``, you have to use the ``$ref`` field:: .. configuration-block:: @@ -462,12 +462,12 @@ General PHP objects .. tip:: **If you're not using the JMS Serializer**, the `Symfony PropertyInfo component`_ is used to describe your models. - It supports doctrine annotations, type hints, and even PHP doc blocks. + It supports doctrine attributes/annotations, type hints, and even PHP doc blocks. It does also support serialization groups when using the Symfony serializer. **If you're using the JMS Serializer**, the metadata of the JMS serializer are used by default to describe your models. Additional information is extracted from the PHP doc block comment, - but the property types must be specified in the JMS annotations. + but the property types must be specified in the JMS attributes/annotations. NOTE: If you are using serialization contexts (e.g. Groups) each permutation will be treated as a separate Path. For example if you have the following two variations defined in different places in your code: @@ -524,7 +524,7 @@ General PHP objects When using the JMS serializer combined with `willdurand/Hateoas`_ (and the `BazingaHateoasBundle`_), HATEOAS metadata are automatically extracted -If you want to customize the documentation of an object's property, you can use ``@OA\Property``:: +If you want to customize the documentation of an object's property, you can use ``#[OA\Property]``:: .. configuration-block:: @@ -585,7 +585,7 @@ If you want to customize the documentation of an object's property, you can use } } -See the `OpenAPI 3.0 specification`__ to see all the available fields of ``@OA\Property``. +See the `OpenAPI 3.0 specification`__ to see all the available fields of ``#[@OA\Property]``. __ https://swagger.io/specification/ diff --git a/docs/security.rst b/docs/security.rst index ca8f915a2..cfa9b0c47 100644 --- a/docs/security.rst +++ b/docs/security.rst @@ -24,7 +24,7 @@ This will add the Bearer security policy to all registered paths. Overriding Specific Paths ------------------------- -The security policy can be overridden for a path using the ``Security`` annotation/attribute. +The security policy can be overridden for a path using the ``Security`` attribute/annotation. .. configuration-block:: @@ -38,7 +38,7 @@ The security policy can be overridden for a path using the ``Security`` annotati #[Security(name: "ApiKeyAuth")] -Notice at the bottom of the docblock is a ``Security`` annotation/attribute with a name of `ApiKeyAuth`. This will override the global security policy to only accept the ``ApiKeyAuth`` policy for this path. +Notice at the bottom of the docblock is a ``Security`` attribute/annotation with a name of `ApiKeyAuth`. This will override the global security policy to only accept the ``ApiKeyAuth`` policy for this path. You can also completely remove security from a path by providing ``Security`` with a name of ``null``. From 64e0384e0b064f9f1ca29fbaad314768ab812072 Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 16:13:48 +0200 Subject: [PATCH 07/11] update docs to no longer reference annotations --- docs/alternative_names.rst | 12 --- docs/areas.rst | 20 +---- docs/faq.rst | 30 +------ docs/index.rst | 170 ++----------------------------------- docs/security.rst | 16 +--- 5 files changed, 13 insertions(+), 235 deletions(-) diff --git a/docs/alternative_names.rst b/docs/alternative_names.rst index 90b1f7cd8..89be057dd 100644 --- a/docs/alternative_names.rst +++ b/docs/alternative_names.rst @@ -40,18 +40,6 @@ In this case the class ``App\Entity\User`` will be aliased into: .. configuration-block:: - .. code-block:: php-annotations - - class HomeController - { - /** - * @OA\Response(response=200, @OA\JsonContent(ref="#/components/schemas/MyModel")) - */ - public function indexAction() - { - } - } - .. code-block:: php-attributes class HomeController diff --git a/docs/areas.rst b/docs/areas.rst index 62511e4f9..2d05439e5 100644 --- a/docs/areas.rst +++ b/docs/areas.rst @@ -79,28 +79,10 @@ the routes that should be documented: internal: with_annotation: true -Then add the attribute/annotation before your controller or action:: +Then add the attribute before your controller or action:: .. configuration-block:: - .. code-block:: php-annotations - - use Nelmio\Annotation as Nelmio; - - /** - * @Nelmio\Areas({"internal"}) => All actions in this controller are documented under the 'internal' area - */ - class MyController - { - /** - * @Nelmio\Areas({"internal"}) => This action is documented under the 'internal' area - */ - public function index() - { - ... - } - } - .. code-block:: php-attributes use Nelmio\Attribute as Nelmio; diff --git a/docs/faq.rst b/docs/faq.rst index 496eb03be..d44fa97c1 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -184,18 +184,6 @@ A: Use ``#[OA\Tag]`` attribute. .. configuration-block:: - .. code-block:: php-annotations - - /** - * Class BookmarkController - * - * @OA\Tag(name="Bookmarks") - */ - class BookmarkController extends AbstractFOSRestController implements ContextPresetInterface - { - // ... - } - .. code-block:: php-attributes /** @@ -228,27 +216,11 @@ Overriding a Form or Plain PHP Object Schema Type Q: I'd like to define a PHP object or form with a type other any ``object``, how do I do that? -A: By using the ``#[OA\Schema]`` attribute/annotation with a ``type`` or ``ref``. +A: By using the ``#[OA\Schema]`` attribute with a ``type`` or ``ref``. Note, however, that a ``type="object"`` will still read all a models properties. .. configuration-block:: - .. code-block:: php-annotations - - use Nelmio\ApiDocBundle\Annotation\Model; - use OpenApi\Annotations as OA; - - /** - * @OA\Schema(type="array", @OA\Items(ref=@Model(type=SomeEntity::class))) - * - * or define a `ref`: - * @OA\Schema(ref="#/components/schemas/SomeRef") - */ - class SomeCollection implements \IteratorAggregate - { - // ... - } - .. code-block:: php-attributes use Nelmio\ApiDocBundle\Attribute\Model; diff --git a/docs/index.rst b/docs/index.rst index 76203f2a4..30f9fa8ec 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,8 +7,8 @@ OpenAPI (Swagger) format and provides a sandbox to interactively experiment with What's supported? ----------------- -This bundle supports *Symfony* route requirements, *Symfony* request mapping (:doc:`symfony_attributes`), PHP annotations, `Swagger-Php`_ annotations, -`FOSRestBundle`_ annotations and applications using `Api-Platform`_. +This bundle supports *Symfony* route requirements, *Symfony* request mapping (:doc:`symfony_attributes`), PHP attributes, `Swagger-Php`_ attributes, +`FOSRestBundle`_ attributes and applications using `Api-Platform`_. .. _`Swagger-Php`: https://github.com/zircote/swagger-php .. _`FOSRestBundle`: https://github.com/FriendsOfSymfony/FOSRestBundle @@ -105,7 +105,7 @@ How does this bundle work? -------------------------- It generates an OpenAPI documentation from your Symfony app thanks to -**Describers**. One extracts data from SwaggerPHP attributes/annotations, one from your +**Describers**. One extracts data from SwaggerPHP attributes, one from your routes, etc. If you configured the ``app.swagger_ui`` route above, you can browse your @@ -151,53 +151,11 @@ You can configure global information in the bundle configuration ``documentation This configuration field can more generally be used to store your documentation as yaml. You may find in the ``.yaml`` files from `SwaggerPHP examples`_. -To document your routes, you can use the SwaggerPHP attributes/annotations and the -``#[Model]`` attribute/annotation in your controllers:: +To document your routes, you can use the SwaggerPHP attributes and the +``#[Model]`` attribute in your controllers:: .. configuration-block:: - .. code-block:: php-annotations - - namespace AppBundle\Controller; - - use AppBundle\Entity\Reward; - use AppBundle\Entity\User; - use Nelmio\ApiDocBundle\Annotation\Model; - use Nelmio\ApiDocBundle\Annotation\Security; - use OpenApi\Annotations as OA; - use Symfony\Component\Routing\Annotation\Route; - - class UserController - { - /** - * List the rewards of the specified user. - * - * This call takes into account all confirmed awards, but not pending or refused awards. - * - * @Route("/api/{user}/rewards", methods={"GET"}) - * @OA\Response( - * response=200, - * description="Returns the rewards of an user", - * @OA\JsonContent( - * type="array", - * @OA\Items(ref=@Model(type=Reward::class, groups={"full"})) - * ) - * ) - * @OA\Parameter( - * name="order", - * in="query", - * description="The field used to order rewards", - * @OA\Schema(type="string") - * ) - * @OA\Tag(name="rewards") - * @Security(name="Bearer") - */ - public function fetchUserRewardsAction(User $user) - { - // ... - } - } - .. code-block:: php-attributes namespace AppBundle\Controller; @@ -270,15 +228,6 @@ This attribute has two options: .. configuration-block:: - .. code-block:: php-annotations - - /** - * @OA\Response( - * response=200, - *     @Model(type=User::class) - * ) - */ - .. code-block:: php-attributes #[OA\Response( @@ -292,15 +241,6 @@ This attribute has two options: .. configuration-block:: - .. code-block:: php-annotations - - /** - * @OA\Response( - * response=200, - *     @Model(type=User::class, groups={"non_sensitive_data"}) - * ) - */ - .. code-block:: php-attributes #[OA\Response( @@ -323,20 +263,6 @@ properties and validator constraints. Take the model class below: .. configuration-block:: - .. code-block:: php-annotations - - use Symfony\Component\Serializer\Annotation\Groups; - use Symfony\Component\Validator\Constraints as Assert; - - class UserDto - { - /** - * @Groups({"default", "create", "update"}) - * @Assert\NotBlank(groups={"default", "create"}) - */ - public string $username; - } - .. code-block:: php-attributes use Symfony\Component\Serializer\Annotation\Groups; @@ -344,8 +270,8 @@ properties and validator constraints. Take the model class below: class UserDto { - #[Groups(["default", "create", "update"])] - #[Assert\NotBlank(groups: ["default", "create"])] + #[Groups(["default", "create", "update"])] + #[Assert\NotBlank(groups: ["default", "create"])] public string $username; } @@ -358,29 +284,6 @@ that property type to not be nullable, for example. .. configuration-block:: - .. code-block:: php-annotations - - use OpenApi\Annotations as OA; - - /** - * shows `username` as `required` in the OpenAPI schema (not nullable) - * @OA\Response( - * response=200, - *     @Model(type=UserDto::class, groups={"default"}) - * ) - */ - - /** - * Similarly, this will make the username `required` in the create - * schema - * @OA\RequestBody(@Model(type=UserDto::class, groups={"create"})) - */ - - /** - * But for updates, the `username` property will not be required - * @OA\RequestBody(@Model(type=UserDto::class, groups={"update"})) - */ - .. code-block:: php-attributes use OpenApi\Attributes as OA; @@ -406,22 +309,6 @@ that property type to not be nullable, for example. .. configuration-block:: - .. code-block:: php-annotations - - /** - * @OA\Response( - * @OA\JsonContent(ref=@Model(type=User::class)) - * ) - * - * or - * - * @OA\Response(@OA\XmlContent( - * @OA\Schema(type="object", - * @OA\Property(property="foo", ref=@Model(type=FooClass::class)) - * ) - * )) - */ - .. code-block:: php-attributes #[OA\Response( @@ -462,12 +349,12 @@ General PHP objects .. tip:: **If you're not using the JMS Serializer**, the `Symfony PropertyInfo component`_ is used to describe your models. - It supports doctrine attributes/annotations, type hints, and even PHP doc blocks. + It supports doctrine attributes, type hints, and even PHP doc blocks. It does also support serialization groups when using the Symfony serializer. **If you're using the JMS Serializer**, the metadata of the JMS serializer are used by default to describe your models. Additional information is extracted from the PHP doc block comment, - but the property types must be specified in the JMS attributes/annotations. + but the property types must be specified in the JMS attributes. NOTE: If you are using serialization contexts (e.g. Groups) each permutation will be treated as a separate Path. For example if you have the following two variations defined in different places in your code: @@ -490,10 +377,6 @@ General PHP objects .. configuration-block:: - .. code-block:: php-annotations - - @OA\Schema(ref=@Model(type="App\Response\ItemResponse", groups=["Default"])), - .. code-block:: php-attributes #[OA\Schema(ref: new Model(type: App\Response\ItemResponse::class, groups: ['Default']))] @@ -513,10 +396,6 @@ General PHP objects .. configuration-block:: - .. code-block:: php-annotations - - /** @OA\Response(response=200, @Model(type=UserDto::class, serializationContext={"useJms"=false})) */ - .. code-block:: php-attributes #[OA\Response(response: 200, content: new Model(type: UserDto::class, serializationContext: ["useJms" => false]))] @@ -529,37 +408,6 @@ If you want to customize the documentation of an object's property, you can use .. 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; diff --git a/docs/security.rst b/docs/security.rst index cfa9b0c47..34f774e57 100644 --- a/docs/security.rst +++ b/docs/security.rst @@ -24,32 +24,20 @@ This will add the Bearer security policy to all registered paths. Overriding Specific Paths ------------------------- -The security policy can be overridden for a path using the ``Security`` attribute/annotation. +The security policy can be overridden for a path using the ``Security`` attribute. .. configuration-block:: - .. code-block:: php-annotations - - /** - * @Security(name="ApiKeyAuth") - */ - .. code-block:: php-attributes #[Security(name: "ApiKeyAuth")] -Notice at the bottom of the docblock is a ``Security`` attribute/annotation with a name of `ApiKeyAuth`. This will override the global security policy to only accept the ``ApiKeyAuth`` policy for this path. +Notice at the bottom of the docblock is a ``Security`` attribute with a name of `ApiKeyAuth`. This will override the global security policy to only accept the ``ApiKeyAuth`` policy for this path. You can also completely remove security from a path by providing ``Security`` with a name of ``null``. .. configuration-block:: - .. code-block:: php-annotations - - /** - * @Security(name=null) - */ - .. code-block:: php-attributes #[Security(name: null)] From 86a158b162b340cfb6eafba9b15265416ef1fe9c Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 16:14:18 +0200 Subject: [PATCH 08/11] remove with_annotation config from docs --- docs/areas.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/areas.rst b/docs/areas.rst index 2d05439e5..e0369f1bb 100644 --- a/docs/areas.rst +++ b/docs/areas.rst @@ -77,7 +77,7 @@ the routes that should be documented: default: path_patterns: [ ^/api ] internal: - with_annotation: true + with_attribute: true Then add the attribute before your controller or action:: From 5a145700c86e13f9a91c269fe66a8be9bde811b8 Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 16:17:59 +0200 Subject: [PATCH 09/11] update symfony bundle config --- .symfony.bundle.yaml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.symfony.bundle.yaml b/.symfony.bundle.yaml index bcd0936cd..020e80c34 100644 --- a/.symfony.bundle.yaml +++ b/.symfony.bundle.yaml @@ -1,6 +1,5 @@ -branches: ["2.x", "3.x", "master"] -maintained_branches: ["3.x", "master"] -current_branch: "master" -dev_branch: "master" -dev_branch_alias: "4.x" -doc_dir: { "3.x": "Resources/doc/", "master": "docs/" } +branches: ["2.x", "3.x", "master", "5.x"] +maintained_branches: ["master", "5.x"] +current_branch: "5.x" +dev_branch: "5.x" +doc_dir: { "3.x": "Resources/doc/", "master": "docs/", "5.x": "docs/" } From 6ca08b772ed4f56180f1e34dfe6285c3e9bbdc5b Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 16:20:31 +0200 Subject: [PATCH 10/11] add composer branch-alias for 5.x --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8884af483..809244d41 100644 --- a/composer.json +++ b/composer.json @@ -92,7 +92,8 @@ }, "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "4.x-dev", + "dev-5.x": "5.x-dev" } }, "scripts-descriptions": { From a8998c2aa5f0d2ce7bd9b49e2ba46f0d6502589d Mon Sep 17 00:00:00 2001 From: djordy Date: Fri, 25 Oct 2024 16:21:24 +0200 Subject: [PATCH 11/11] update UPGRADE-5.0.md --- UPGRADE-5.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index 642d662bd..8f132674a 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -26,7 +26,7 @@ This causes the following breaking changes in classes that used annotations: - BC BREAK: Removed 1st parameter `?Reader $annotationReader` from `Nelmio\ApiDocBundle\RouteDescriber\FosRestDescriber::__construct()` - BC BREAK: Removed 1st parameter `?Reader $annotationReader` from `Nelmio\ApiDocBundle\Routing\FilteredRouteCollectionBuilder::__construct()` -## BC BREAK: `Nelmio\ApiDocBundle\Annotation` namespace has been moved to `Nelmio\ApiDocBundle\Attribute` +## BC BREAK: `Nelmio\ApiDocBundle\Annotation` namespace has been remove in favor of `Nelmio\ApiDocBundle\Attribute` ## BC BREAK: Configuration option `with_annotation` has been renamed to `with_attribute` ```diff